summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Benvenuto <mark.benvenuto@mongodb.com>2017-06-30 15:19:38 -0400
committerMark Benvenuto <mark.benvenuto@mongodb.com>2018-03-12 15:46:23 -0400
commit2b8d573e40fe26b9285a053ed3b7a8e62f68c2e2 (patch)
tree1cd45d923371e36d88e02cf672b3b47fc244b2df
parentc3860652ccb14862b132d95df4f034230c7423e1 (diff)
downloadmongo-2b8d573e40fe26b9285a053ed3b7a8e62f68c2e2.tar.gz
SERVER-29938 FTDC Refactor
(cherry picked from commit 4d8405a45c7be94f1022ae3d3de4731e2bf9632b)
-rw-r--r--src/mongo/db/db.cpp4
-rw-r--r--src/mongo/db/ftdc/SConscript21
-rw-r--r--src/mongo/db/ftdc/compressor_test.cpp2
-rw-r--r--src/mongo/db/ftdc/constants.h6
-rw-r--r--src/mongo/db/ftdc/ftdc_mongod.cpp323
-rw-r--r--src/mongo/db/ftdc/ftdc_mongod.h56
-rw-r--r--src/mongo/db/ftdc/ftdc_server.cpp343
-rw-r--r--src/mongo/db/ftdc/ftdc_server.h85
-rw-r--r--src/mongo/db/ftdc/ftdc_system_stats.h1
9 files changed, 492 insertions, 349 deletions
diff --git a/src/mongo/db/db.cpp b/src/mongo/db/db.cpp
index 96456fdd558..c6272425bf5 100644
--- a/src/mongo/db/db.cpp
+++ b/src/mongo/db/db.cpp
@@ -756,7 +756,7 @@ ExitCode _initAndListen(int listenPort) {
if (!storageGlobalParams.readOnly) {
logStartup(startupOpCtx.get());
- startFTDC();
+ startMongoDFTDC();
getDeleter()->startWorkers();
@@ -1112,7 +1112,7 @@ static void shutdownTask() {
#endif
// Shutdown Full-Time Data Capture
- stopFTDC();
+ stopMongoDFTDC();
if (txn) {
ShardingState::get(txn)->shutDown(txn);
diff --git a/src/mongo/db/ftdc/SConscript b/src/mongo/db/ftdc/SConscript
index 0d16aec93f2..24e56710ddd 100644
--- a/src/mongo/db/ftdc/SConscript
+++ b/src/mongo/db/ftdc/SConscript
@@ -21,7 +21,6 @@ ftdcEnv.Library(
LIBDEPS=[
'$BUILD_DIR/mongo/base',
'$BUILD_DIR/mongo/bson/util/bson_extract',
- '$BUILD_DIR/mongo/db/server_options_core',
'$BUILD_DIR/mongo/db/service_context',
'$BUILD_DIR/third_party/s2/s2', # For VarInt
'$BUILD_DIR/third_party/shim_zlib',
@@ -40,24 +39,34 @@ elif env.TargetOSIs('windows'):
]
env.Library(
- target='ftdc_mongod',
+ target='ftdc_server',
source=[
- 'ftdc_commands.cpp',
- 'ftdc_mongod.cpp',
+ 'ftdc_server.cpp',
'ftdc_system_stats.cpp',
'ftdc_system_stats_${TARGET_OS}.cpp',
],
LIBDEPS=[
'$BUILD_DIR/mongo/base',
'$BUILD_DIR/mongo/db/commands',
- '$BUILD_DIR/mongo/db/repl/repl_coordinator_global',
'$BUILD_DIR/mongo/db/server_parameters',
- '$BUILD_DIR/mongo/db/storage/storage_options',
'$BUILD_DIR/mongo/util/processinfo',
'ftdc'
] + platform_libs,
)
+env.Library(
+ target='ftdc_mongod',
+ source=[
+ 'ftdc_commands.cpp',
+ 'ftdc_mongod.cpp',
+ ],
+ LIBDEPS=[
+ '$BUILD_DIR/mongo/db/repl/repl_coordinator_global',
+ '$BUILD_DIR/mongo/db/storage/storage_options',
+ 'ftdc_server'
+ ],
+)
+
env.CppUnitTest(
target='ftdc_test',
source=[
diff --git a/src/mongo/db/ftdc/compressor_test.cpp b/src/mongo/db/ftdc/compressor_test.cpp
index 688197a392a..0c01bd58040 100644
--- a/src/mongo/db/ftdc/compressor_test.cpp
+++ b/src/mongo/db/ftdc/compressor_test.cpp
@@ -368,7 +368,7 @@ TEST(FTDCCompressor, TestNumbersCompat) {
}
// Test various date time types
-TEST(AFTDCCompressor, TestDateTimeTypes) {
+TEST(FTDCCompressor, TestDateTimeTypes) {
TestTie c;
for (int i = 0; i < 10; i++) {
BSONObjBuilder builder1;
diff --git a/src/mongo/db/ftdc/constants.h b/src/mongo/db/ftdc/constants.h
index a989fd35b64..3fe5191ff44 100644
--- a/src/mongo/db/ftdc/constants.h
+++ b/src/mongo/db/ftdc/constants.h
@@ -26,6 +26,10 @@
* then also delete it in the license file.
*/
+#pragma once
+
+#include "mongo/base/string_data.h"
+
namespace mongo {
extern const char kFTDCInterimFile[];
@@ -42,4 +46,6 @@ extern const char kFTDCDocsField[];
extern const char kFTDCCollectStartField[];
extern const char kFTDCCollectEndField[];
+constexpr StringData kFTDCDefaultDirectory = "diagnostic.data"_sd;
+
} // namespace mongo
diff --git a/src/mongo/db/ftdc/ftdc_mongod.cpp b/src/mongo/db/ftdc/ftdc_mongod.cpp
index 094a2b05d06..32f5e4b27f6 100644
--- a/src/mongo/db/ftdc/ftdc_mongod.cpp
+++ b/src/mongo/db/ftdc/ftdc_mongod.cpp
@@ -31,295 +31,18 @@
#include "mongo/db/ftdc/ftdc_mongod.h"
#include <boost/filesystem.hpp>
-#include <fstream>
-#include <memory>
-#include "mongo/base/init.h"
-#include "mongo/base/status.h"
-#include "mongo/bson/bsonobjbuilder.h"
-#include "mongo/db/commands.h"
-#include "mongo/db/ftdc/collector.h"
-#include "mongo/db/ftdc/config.h"
+#include "mongo/db/ftdc/constants.h"
#include "mongo/db/ftdc/controller.h"
-#include "mongo/db/ftdc/ftdc_system_stats.h"
-#include "mongo/db/jsobj.h"
+#include "mongo/db/ftdc/ftdc_server.h"
#include "mongo/db/repl/replication_coordinator.h"
#include "mongo/db/repl/replication_coordinator_global.h"
-#include "mongo/db/server_parameters.h"
-#include "mongo/db/service_context.h"
#include "mongo/db/storage/storage_options.h"
namespace mongo {
namespace {
-
-const auto getFTDCController = ServiceContext::declareDecoration<std::unique_ptr<FTDCController>>();
-
-FTDCController* getGlobalFTDCController() {
- if (!hasGlobalServiceContext()) {
- return nullptr;
- }
-
- return getFTDCController(getGlobalServiceContext()).get();
-}
-
-std::atomic<bool> localEnabledFlag(FTDCConfig::kEnabledDefault); // NOLINT
-
-class ExportedFTDCEnabledParameter
- : public ExportedServerParameter<bool, ServerParameterType::kStartupAndRuntime> {
-public:
- ExportedFTDCEnabledParameter()
- : ExportedServerParameter<bool, ServerParameterType::kStartupAndRuntime>(
- ServerParameterSet::getGlobal(),
- "diagnosticDataCollectionEnabled",
- &localEnabledFlag) {}
-
- virtual Status validate(const bool& potentialNewValue) {
- auto controller = getGlobalFTDCController();
- if (controller) {
- controller->setEnabled(potentialNewValue);
- }
-
- return Status::OK();
- }
-
-} exportedFTDCEnabledParameter;
-
-std::atomic<std::int32_t> localPeriodMillis(FTDCConfig::kPeriodMillisDefault); // NOLINT
-
-class ExportedFTDCPeriodParameter
- : public ExportedServerParameter<std::int32_t, ServerParameterType::kStartupAndRuntime> {
-public:
- ExportedFTDCPeriodParameter()
- : ExportedServerParameter<std::int32_t, ServerParameterType::kStartupAndRuntime>(
- ServerParameterSet::getGlobal(),
- "diagnosticDataCollectionPeriodMillis",
- &localPeriodMillis) {}
-
- virtual Status validate(const std::int32_t& potentialNewValue) {
- if (potentialNewValue < 100) {
- return Status(
- ErrorCodes::BadValue,
- "diagnosticDataCollectionPeriodMillis must be greater than or equal to 100ms");
- }
-
- auto controller = getGlobalFTDCController();
- if (controller) {
- controller->setPeriod(Milliseconds(potentialNewValue));
- }
-
- return Status::OK();
- }
-
-} exportedFTDCPeriodParameter;
-
-// Scale the values down since are defaults are in bytes, but the user interface is MB
-std::atomic<std::int32_t> localMaxDirectorySizeMB( // NOLINT
- FTDCConfig::kMaxDirectorySizeBytesDefault / (1024 * 1024));
-
-std::atomic<std::int32_t> localMaxFileSizeMB(FTDCConfig::kMaxFileSizeBytesDefault / // NOLINT
- (1024 * 1024));
-
-class ExportedFTDCDirectorySizeParameter
- : public ExportedServerParameter<std::int32_t, ServerParameterType::kStartupAndRuntime> {
-public:
- ExportedFTDCDirectorySizeParameter()
- : ExportedServerParameter<std::int32_t, ServerParameterType::kStartupAndRuntime>(
- ServerParameterSet::getGlobal(),
- "diagnosticDataCollectionDirectorySizeMB",
- &localMaxDirectorySizeMB) {}
-
- virtual Status validate(const std::int32_t& potentialNewValue) {
- if (potentialNewValue < 10) {
- return Status(
- ErrorCodes::BadValue,
- "diagnosticDataCollectionDirectorySizeMB must be greater than or equal to 10");
- }
-
- if (potentialNewValue < localMaxFileSizeMB) {
- return Status(
- ErrorCodes::BadValue,
- str::stream()
- << "diagnosticDataCollectionDirectorySizeMB must be greater than or equal to '"
- << localMaxFileSizeMB
- << "' which is the current value of diagnosticDataCollectionFileSizeMB.");
- }
-
- auto controller = getGlobalFTDCController();
- if (controller) {
- controller->setMaxDirectorySizeBytes(potentialNewValue * 1024 * 1024);
- }
-
- return Status::OK();
- }
-
-} exportedFTDCDirectorySizeParameter;
-
-class ExportedFTDCFileSizeParameter
- : public ExportedServerParameter<std::int32_t, ServerParameterType::kStartupAndRuntime> {
-public:
- ExportedFTDCFileSizeParameter()
- : ExportedServerParameter<std::int32_t, ServerParameterType::kStartupAndRuntime>(
- ServerParameterSet::getGlobal(),
- "diagnosticDataCollectionFileSizeMB",
- &localMaxFileSizeMB) {}
-
- virtual Status validate(const std::int32_t& potentialNewValue) {
- if (potentialNewValue < 1) {
- return Status(ErrorCodes::BadValue,
- "diagnosticDataCollectionFileSizeMB must be greater than or equal to 1");
- }
-
- if (potentialNewValue > localMaxDirectorySizeMB) {
- return Status(
- ErrorCodes::BadValue,
- str::stream()
- << "diagnosticDataCollectionFileSizeMB must be less than or equal to '"
- << localMaxDirectorySizeMB
- << "' which is the current value of diagnosticDataCollectionDirectorySizeMB.");
- }
-
- auto controller = getGlobalFTDCController();
- if (controller) {
- controller->setMaxFileSizeBytes(potentialNewValue * 1024 * 1024);
- }
-
- return Status::OK();
- }
-
-} exportedFTDCFileSizeParameter;
-
-std::atomic<std::int32_t> localMaxSamplesPerArchiveMetricChunk( // NOLINT
- FTDCConfig::kMaxSamplesPerArchiveMetricChunkDefault);
-
-class ExportedFTDCArchiveChunkSizeParameter
- : public ExportedServerParameter<std::int32_t, ServerParameterType::kStartupAndRuntime> {
-public:
- ExportedFTDCArchiveChunkSizeParameter()
- : ExportedServerParameter<std::int32_t, ServerParameterType::kStartupAndRuntime>(
- ServerParameterSet::getGlobal(),
- "diagnosticDataCollectionSamplesPerChunk",
- &localMaxSamplesPerArchiveMetricChunk) {}
-
- virtual Status validate(const std::int32_t& potentialNewValue) {
- if (potentialNewValue < 2) {
- return Status(
- ErrorCodes::BadValue,
- "diagnosticDataCollectionSamplesPerChunk must be greater than or equal to 2");
- }
-
- auto controller = getGlobalFTDCController();
- if (controller) {
- controller->setMaxSamplesPerArchiveMetricChunk(potentialNewValue);
- }
-
- return Status::OK();
- }
-
-} exportedFTDCArchiveChunkSizeParameter;
-
-std::atomic<std::int32_t> localMaxSamplesPerInterimMetricChunk( // NOLINT
- FTDCConfig::kMaxSamplesPerInterimMetricChunkDefault);
-
-class ExportedFTDCInterimChunkSizeParameter
- : public ExportedServerParameter<std::int32_t, ServerParameterType::kStartupAndRuntime> {
-public:
- ExportedFTDCInterimChunkSizeParameter()
- : ExportedServerParameter<std::int32_t, ServerParameterType::kStartupAndRuntime>(
- ServerParameterSet::getGlobal(),
- "diagnosticDataCollectionSamplesPerInterimUpdate",
- &localMaxSamplesPerInterimMetricChunk) {}
-
- virtual Status validate(const std::int32_t& potentialNewValue) {
- if (potentialNewValue < 2) {
- return Status(ErrorCodes::BadValue,
- "diagnosticDataCollectionSamplesPerInterimUpdate must be greater than or "
- "equal to 2");
- }
-
- auto controller = getGlobalFTDCController();
- if (controller) {
- controller->setMaxSamplesPerInterimMetricChunk(potentialNewValue);
- }
-
- return Status::OK();
- }
-
-} exportedFTDCInterimChunkSizeParameter;
-
-class FTDCSimpleInternalCommandCollector final : public FTDCCollectorInterface {
-public:
- FTDCSimpleInternalCommandCollector(StringData command,
- StringData name,
- StringData ns,
- BSONObj cmdObj)
- : _name(name.toString()), _ns(ns.toString()), _cmdObj(std::move(cmdObj)) {
- _command = Command::findCommand(command);
- invariant(_command);
- }
-
- void collect(OperationContext* txn, BSONObjBuilder& builder) override {
- std::string errmsg;
-
- bool ret = _command->run(txn, _ns, _cmdObj, 0, errmsg, builder);
-
- // Some commands return errmsgs when they return false (collstats)
- // Some commands return bson objs when they return false (replGetStatus)
- // We append the status as needed to ensure readers of the collected data can check the
- // status of any individual command.
- _command->appendCommandStatus(builder, ret, errmsg);
- }
-
- std::string name() const override {
- return _name;
- }
-
-private:
- std::string _name;
- std::string _ns;
- BSONObj _cmdObj;
-
- // Not owned
- Command* _command;
-};
-
-} // namespace
-
-// Register the FTDC system
-// Note: This must be run before the server parameters are parsed during startup
-// so that the FTDCController is initialized.
-//
-void startFTDC() {
- boost::filesystem::path dir(storageGlobalParams.dbpath);
- dir /= "diagnostic.data";
-
-
- FTDCConfig config;
- config.period = Milliseconds(localPeriodMillis.load());
- config.enabled = localEnabledFlag;
- config.maxFileSizeBytes = localMaxFileSizeMB * 1024 * 1024;
- config.maxDirectorySizeBytes = localMaxDirectorySizeMB * 1024 * 1024;
- config.maxSamplesPerArchiveMetricChunk = localMaxSamplesPerArchiveMetricChunk;
- config.maxSamplesPerInterimMetricChunk = localMaxSamplesPerInterimMetricChunk;
-
- auto controller = stdx::make_unique<FTDCController>(dir, config);
-
- // Install periodic collectors
- // These are collected on the period interval in FTDCConfig.
- // NOTE: For each command here, there must be an equivalent privilege check in
- // GetDiagnosticDataCommand
-
- // CmdServerStatus
- // The "sharding" section is filtered out because at this time it only consists of strings in
- // migration status. This section triggers too many schema changes in the serverStatus which
- // hurt ftdc compression efficiency, because its output varies depending on the list of active
- // migrations.
- controller->addPeriodicCollector(stdx::make_unique<FTDCSimpleInternalCommandCollector>(
- "serverStatus",
- "serverStatus",
- "",
- BSON("serverStatus" << 1 << "tcMalloc" << true << "sharding" << false)));
-
+void registerMongoDCollectors(FTDCController* controller) {
// These metrics are only collected if replication is enabled
if (repl::getGlobalReplicationCoordinator()->getReplicationMode() !=
repl::ReplicationCoordinator::modeNone) {
@@ -335,43 +58,19 @@ void startFTDC() {
BSON("collStats"
<< "oplog.rs")));
}
-
- // Install System Metric Collector as a periodic collector
- installSystemMetricsCollector(controller.get());
-
- // Install file rotation collectors
- // These are collected on each file rotation.
-
- // CmdBuildInfo
- controller->addOnRotateCollector(stdx::make_unique<FTDCSimpleInternalCommandCollector>(
- "buildInfo", "buildInfo", "", BSON("buildInfo" << 1)));
-
- // CmdGetCmdLineOpts
- controller->addOnRotateCollector(stdx::make_unique<FTDCSimpleInternalCommandCollector>(
- "getCmdLineOpts", "getCmdLineOpts", "", BSON("getCmdLineOpts" << 1)));
-
- // HostInfoCmd
- controller->addOnRotateCollector(stdx::make_unique<FTDCSimpleInternalCommandCollector>(
- "hostInfo", "hostInfo", "", BSON("hostInfo" << 1)));
-
- // Install the new controller
- auto& staticFTDC = getFTDCController(getGlobalServiceContext());
-
- staticFTDC = std::move(controller);
-
- staticFTDC->start();
}
-void stopFTDC() {
- auto controller = getGlobalFTDCController();
+} // namespace
- if (controller) {
- controller->stop();
- }
+void startMongoDFTDC() {
+ boost::filesystem::path dir(storageGlobalParams.dbpath);
+ dir /= kFTDCDefaultDirectory.toString();
+
+ startFTDC(dir, registerMongoDCollectors);
}
-FTDCController* FTDCController::get(ServiceContext* serviceContext) {
- return getFTDCController(serviceContext).get();
+void stopMongoDFTDC() {
+ stopFTDC();
}
} // namespace mongo
diff --git a/src/mongo/db/ftdc/ftdc_mongod.h b/src/mongo/db/ftdc/ftdc_mongod.h
index 1e4f20b8b17..b4409dde902 100644
--- a/src/mongo/db/ftdc/ftdc_mongod.h
+++ b/src/mongo/db/ftdc/ftdc_mongod.h
@@ -1,30 +1,30 @@
/**
-* Copyright (C) 2015 MongoDB Inc.
-*
-* This program is free software: you can redistribute it and/or modify
-* it under the terms of the GNU Affero General Public License, version 3,
-* as published by the Free Software Foundation.
-*
-* 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
-* GNU Affero General Public License for more details.
-*
-* You should have received a copy of the GNU Affero General Public License
-* along with this program. If not, see <http://www.gnu.org/licenses/>.
-*
-* 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 GNU Affero General 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.
-*/
+ * Copyright (C) 2015 MongoDB Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * 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 GNU Affero General 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
@@ -34,11 +34,11 @@ namespace mongo {
* Start Full Time Data Capture
* Starts 1 thread.
*/
-void startFTDC();
+void startMongoDFTDC();
/**
* Stop Full Time Data Capture
*/
-void stopFTDC();
+void stopMongoDFTDC();
} // namespace mongo
diff --git a/src/mongo/db/ftdc/ftdc_server.cpp b/src/mongo/db/ftdc/ftdc_server.cpp
new file mode 100644
index 00000000000..6126434e8d5
--- /dev/null
+++ b/src/mongo/db/ftdc/ftdc_server.cpp
@@ -0,0 +1,343 @@
+/**
+ * Copyright (C) 2017 MongoDB Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * 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 GNU Affero General 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/ftdc/ftdc_server.h"
+
+#include <boost/filesystem.hpp>
+#include <fstream>
+#include <memory>
+
+#include "mongo/base/status.h"
+#include "mongo/bson/bsonobjbuilder.h"
+#include "mongo/db/commands.h"
+#include "mongo/db/ftdc/collector.h"
+#include "mongo/db/ftdc/config.h"
+#include "mongo/db/ftdc/controller.h"
+#include "mongo/db/ftdc/ftdc_system_stats.h"
+#include "mongo/db/jsobj.h"
+#include "mongo/db/server_parameters.h"
+#include "mongo/db/service_context.h"
+#include "mongo/stdx/memory.h"
+
+namespace mongo {
+
+namespace {
+
+const auto getFTDCController = ServiceContext::declareDecoration<std::unique_ptr<FTDCController>>();
+
+FTDCController* getGlobalFTDCController() {
+ if (!hasGlobalServiceContext()) {
+ return nullptr;
+ }
+
+ return getFTDCController(getGlobalServiceContext()).get();
+}
+
+std::atomic<bool> localEnabledFlag(FTDCConfig::kEnabledDefault); // NOLINT
+
+class ExportedFTDCEnabledParameter
+ : public ExportedServerParameter<bool, ServerParameterType::kStartupAndRuntime> {
+public:
+ ExportedFTDCEnabledParameter()
+ : ExportedServerParameter<bool, ServerParameterType::kStartupAndRuntime>(
+ ServerParameterSet::getGlobal(),
+ "diagnosticDataCollectionEnabled",
+ &localEnabledFlag) {}
+
+ virtual Status validate(const bool& potentialNewValue) {
+ auto controller = getGlobalFTDCController();
+ if (controller) {
+ controller->setEnabled(potentialNewValue);
+ }
+
+ return Status::OK();
+ }
+
+} exportedFTDCEnabledParameter;
+
+std::atomic<std::int32_t> localPeriodMillis(FTDCConfig::kPeriodMillisDefault); // NOLINT
+
+class ExportedFTDCPeriodParameter
+ : public ExportedServerParameter<std::int32_t, ServerParameterType::kStartupAndRuntime> {
+public:
+ ExportedFTDCPeriodParameter()
+ : ExportedServerParameter<std::int32_t, ServerParameterType::kStartupAndRuntime>(
+ ServerParameterSet::getGlobal(),
+ "diagnosticDataCollectionPeriodMillis",
+ &localPeriodMillis) {}
+
+ virtual Status validate(const std::int32_t& potentialNewValue) {
+ if (potentialNewValue < 100) {
+ return Status(
+ ErrorCodes::BadValue,
+ "diagnosticDataCollectionPeriodMillis must be greater than or equal to 100ms");
+ }
+
+ auto controller = getGlobalFTDCController();
+ if (controller) {
+ controller->setPeriod(Milliseconds(potentialNewValue));
+ }
+
+ return Status::OK();
+ }
+
+} exportedFTDCPeriodParameter;
+
+// Scale the values down since are defaults are in bytes, but the user interface is MB
+std::atomic<std::int32_t> localMaxDirectorySizeMB(FTDCConfig::kMaxDirectorySizeBytesDefault / (1024 * 1024)); // NOLINT
+
+std::atomic<std::int32_t> localMaxFileSizeMB(FTDCConfig::kMaxFileSizeBytesDefault / (1024 * 1024)); // NOLINT
+
+class ExportedFTDCDirectorySizeParameter
+ : public ExportedServerParameter<std::int32_t, ServerParameterType::kStartupAndRuntime> {
+public:
+ ExportedFTDCDirectorySizeParameter()
+ : ExportedServerParameter<std::int32_t, ServerParameterType::kStartupAndRuntime>(
+ ServerParameterSet::getGlobal(),
+ "diagnosticDataCollectionDirectorySizeMB",
+ &localMaxDirectorySizeMB) {}
+
+ virtual Status validate(const std::int32_t& potentialNewValue) {
+ if (potentialNewValue < 10) {
+ return Status(
+ ErrorCodes::BadValue,
+ "diagnosticDataCollectionDirectorySizeMB must be greater than or equal to 10");
+ }
+
+ if (potentialNewValue < localMaxFileSizeMB.load()) {
+ return Status(
+ ErrorCodes::BadValue,
+ str::stream()
+ << "diagnosticDataCollectionDirectorySizeMB must be greater than or equal to '"
+ << localMaxFileSizeMB.load()
+ << "' which is the current value of diagnosticDataCollectionFileSizeMB.");
+ }
+
+ auto controller = getGlobalFTDCController();
+ if (controller) {
+ controller->setMaxDirectorySizeBytes(potentialNewValue * 1024 * 1024);
+ }
+
+ return Status::OK();
+ }
+
+} exportedFTDCDirectorySizeParameter;
+
+class ExportedFTDCFileSizeParameter
+ : public ExportedServerParameter<std::int32_t, ServerParameterType::kStartupAndRuntime> {
+public:
+ ExportedFTDCFileSizeParameter()
+ : ExportedServerParameter<std::int32_t, ServerParameterType::kStartupAndRuntime>(
+ ServerParameterSet::getGlobal(),
+ "diagnosticDataCollectionFileSizeMB",
+ &localMaxFileSizeMB) {}
+
+ virtual Status validate(const std::int32_t& potentialNewValue) {
+ if (potentialNewValue < 1) {
+ return Status(ErrorCodes::BadValue,
+ "diagnosticDataCollectionFileSizeMB must be greater than or equal to 1");
+ }
+
+ if (potentialNewValue > localMaxDirectorySizeMB.load()) {
+ return Status(
+ ErrorCodes::BadValue,
+ str::stream()
+ << "diagnosticDataCollectionFileSizeMB must be less than or equal to '"
+ << localMaxDirectorySizeMB.load()
+ << "' which is the current value of diagnosticDataCollectionDirectorySizeMB.");
+ }
+
+ auto controller = getGlobalFTDCController();
+ if (controller) {
+ controller->setMaxFileSizeBytes(potentialNewValue * 1024 * 1024);
+ }
+
+ return Status::OK();
+ }
+
+} exportedFTDCFileSizeParameter;
+
+std::atomic<std::int32_t> localMaxSamplesPerArchiveMetricChunk( // NOLINT
+ FTDCConfig::kMaxSamplesPerArchiveMetricChunkDefault);
+
+class ExportedFTDCArchiveChunkSizeParameter
+ : public ExportedServerParameter<std::int32_t, ServerParameterType::kStartupAndRuntime> {
+public:
+ ExportedFTDCArchiveChunkSizeParameter()
+ : ExportedServerParameter<std::int32_t, ServerParameterType::kStartupAndRuntime>(
+ ServerParameterSet::getGlobal(),
+ "diagnosticDataCollectionSamplesPerChunk",
+ &localMaxSamplesPerArchiveMetricChunk) {}
+
+ virtual Status validate(const std::int32_t& potentialNewValue) {
+ if (potentialNewValue < 2) {
+ return Status(
+ ErrorCodes::BadValue,
+ "diagnosticDataCollectionSamplesPerChunk must be greater than or equal to 2");
+ }
+
+ auto controller = getGlobalFTDCController();
+ if (controller) {
+ controller->setMaxSamplesPerArchiveMetricChunk(potentialNewValue);
+ }
+
+ return Status::OK();
+ }
+
+} exportedFTDCArchiveChunkSizeParameter;
+
+std::atomic<std::int32_t> localMaxSamplesPerInterimMetricChunk( // NOLINT
+ FTDCConfig::kMaxSamplesPerInterimMetricChunkDefault);
+
+class ExportedFTDCInterimChunkSizeParameter
+ : public ExportedServerParameter<std::int32_t, ServerParameterType::kStartupAndRuntime> {
+public:
+ ExportedFTDCInterimChunkSizeParameter()
+ : ExportedServerParameter<std::int32_t, ServerParameterType::kStartupAndRuntime>(
+ ServerParameterSet::getGlobal(),
+ "diagnosticDataCollectionSamplesPerInterimUpdate",
+ &localMaxSamplesPerInterimMetricChunk) {}
+
+ virtual Status validate(const std::int32_t& potentialNewValue) {
+ if (potentialNewValue < 2) {
+ return Status(ErrorCodes::BadValue,
+ "diagnosticDataCollectionSamplesPerInterimUpdate must be greater than or "
+ "equal to 2");
+ }
+
+ auto controller = getGlobalFTDCController();
+ if (controller) {
+ controller->setMaxSamplesPerInterimMetricChunk(potentialNewValue);
+ }
+
+ return Status::OK();
+ }
+
+} exportedFTDCInterimChunkSizeParameter;
+} // namespace
+
+FTDCSimpleInternalCommandCollector::FTDCSimpleInternalCommandCollector(StringData command,
+ StringData name,
+ StringData ns,
+ BSONObj cmdObj)
+ : _name(name.toString()), _ns(ns.toString()), _cmdObj(std::move(cmdObj)) {
+ _command = Command::findCommand(command);
+ invariant(_command);
+}
+
+void FTDCSimpleInternalCommandCollector::collect(OperationContext* opCtx, BSONObjBuilder& builder) {
+ std::string errmsg;
+
+ bool ret = _command->run(opCtx, _ns, _cmdObj, 0, errmsg, builder);
+
+ // Some commands return errmsgs when they return false (collstats)
+ // Some commands return bson objs when they return false (replGetStatus)
+ // We append the status as needed to ensure readers of the collected data can check the
+ // status of any individual command.
+ _command->appendCommandStatus(builder, ret, errmsg);
+}
+
+std::string FTDCSimpleInternalCommandCollector::name() const {
+ return _name;
+}
+
+// Register the FTDC system
+// Note: This must be run before the server parameters are parsed during startup
+// so that the FTDCController is initialized.
+//
+void startFTDC(boost::filesystem::path& path, RegisterCollectorsFunction registerCollectors) {
+ FTDCConfig config;
+ config.period = Milliseconds(localPeriodMillis.load());
+ config.enabled = localEnabledFlag.load();
+ config.maxFileSizeBytes = localMaxFileSizeMB.load() * 1024 * 1024;
+ config.maxDirectorySizeBytes = localMaxDirectorySizeMB.load() * 1024 * 1024;
+ config.maxSamplesPerArchiveMetricChunk = localMaxSamplesPerArchiveMetricChunk.load();
+ config.maxSamplesPerInterimMetricChunk = localMaxSamplesPerInterimMetricChunk.load();
+
+ auto controller = stdx::make_unique<FTDCController>(path, config);
+
+ // Install periodic collectors
+ // These are collected on the period interval in FTDCConfig.
+ // NOTE: For each command here, there must be an equivalent privilege check in
+ // GetDiagnosticDataCommand
+
+ // CmdServerStatus
+ // The "sharding" section is filtered out because at this time it only consists of strings in
+ // migration status. This section triggers too many schema changes in the serverStatus which
+ // hurt ftdc compression efficiency, because its output varies depending on the list of active
+ // migrations.
+ // TODO: do we need to enable "sharding" on MongoS?
+ controller->addPeriodicCollector(stdx::make_unique<FTDCSimpleInternalCommandCollector>(
+ "serverStatus",
+ "serverStatus",
+ "",
+ BSON("serverStatus" << 1 << "tcMalloc" << true << "sharding" << false)));
+
+ registerCollectors(controller.get());
+
+ // Install System Metric Collector as a periodic collector
+ installSystemMetricsCollector(controller.get());
+
+ // Install file rotation collectors
+ // These are collected on each file rotation.
+
+ // CmdBuildInfo
+ controller->addOnRotateCollector(stdx::make_unique<FTDCSimpleInternalCommandCollector>(
+ "buildInfo", "buildInfo", "", BSON("buildInfo" << 1)));
+
+ // CmdGetCmdLineOpts
+ controller->addOnRotateCollector(stdx::make_unique<FTDCSimpleInternalCommandCollector>(
+ "getCmdLineOpts", "getCmdLineOpts", "", BSON("getCmdLineOpts" << 1)));
+
+ // HostInfoCmd
+ controller->addOnRotateCollector(stdx::make_unique<FTDCSimpleInternalCommandCollector>(
+ "hostInfo", "hostInfo", "", BSON("hostInfo" << 1)));
+
+ // Install the new controller
+ auto& staticFTDC = getFTDCController(getGlobalServiceContext());
+
+ staticFTDC = std::move(controller);
+
+ staticFTDC->start();
+}
+
+void stopFTDC() {
+ auto controller = getGlobalFTDCController();
+
+ if (controller) {
+ controller->stop();
+ }
+}
+
+FTDCController* FTDCController::get(ServiceContext* serviceContext) {
+ return getFTDCController(serviceContext).get();
+}
+
+} // namespace mongo
diff --git a/src/mongo/db/ftdc/ftdc_server.h b/src/mongo/db/ftdc/ftdc_server.h
new file mode 100644
index 00000000000..b9f238801cd
--- /dev/null
+++ b/src/mongo/db/ftdc/ftdc_server.h
@@ -0,0 +1,85 @@
+/**
+ * Copyright (C) 2017 MongoDB Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * 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 GNU Affero General Public License in all respects
+ * for all of the code used other than as permitted herein. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you do not
+ * wish to do so, delete this exception statement from your version. If you
+ * delete this exception statement from all source files in the program,
+ * then also delete it in the license file.
+ */
+
+#pragma once
+
+#include <string>
+
+#include "mongo/bson/bsonobjbuilder.h"
+#include "mongo/db/commands.h"
+#include "mongo/db/ftdc/collector.h"
+#include "mongo/db/ftdc/controller.h"
+#include "mongo/db/jsobj.h"
+#include "mongo/db/operation_context.h"
+#include "mongo/stdx/functional.h"
+
+namespace mongo {
+
+/**
+ * Function that allows FTDC server components to register their own collectors as needed.
+ */
+using RegisterCollectorsFunction = stdx::function<void(FTDCController*)>;
+
+/**
+ * Start Full Time Data Capture
+ * Starts 1 thread.
+ *
+ * See MongoD and MongoS specific functions.
+ */
+void startFTDC(boost::filesystem::path& path, RegisterCollectorsFunction registerCollectors);
+
+/**
+ * Stop Full Time Data Capture
+ *
+ * See MongoD and MongoS specific functions.
+ */
+void stopFTDC();
+
+/**
+ * A simple FTDC Collector that runs Commands.
+ */
+class FTDCSimpleInternalCommandCollector final : public FTDCCollectorInterface {
+public:
+ FTDCSimpleInternalCommandCollector(StringData command,
+ StringData name,
+ StringData ns,
+ BSONObj cmdObj);
+
+ void collect(OperationContext* opCtx, BSONObjBuilder& builder) override;
+ std::string name() const override;
+
+private:
+ std::string _name;
+ std::string _ns;
+ BSONObj _cmdObj;
+
+ // Not owned
+ Command* _command;
+};
+
+} // namespace mongo
diff --git a/src/mongo/db/ftdc/ftdc_system_stats.h b/src/mongo/db/ftdc/ftdc_system_stats.h
index 20d21ef4f39..97bc0a67cf5 100644
--- a/src/mongo/db/ftdc/ftdc_system_stats.h
+++ b/src/mongo/db/ftdc/ftdc_system_stats.h
@@ -25,6 +25,7 @@
* delete this exception statement from all source files in the program,
* then also delete it in the license file.
*/
+#pragma once
#include <string>