summaryrefslogtreecommitdiff
path: root/src/mongo/db/ftdc
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/ftdc')
-rw-r--r--src/mongo/db/ftdc/SConscript31
-rw-r--r--src/mongo/db/ftdc/collector.cpp1
-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/controller.cpp31
-rw-r--r--src/mongo/db/ftdc/controller.h15
-rw-r--r--src/mongo/db/ftdc/controller_test.cpp2
-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_mongos.cpp153
-rw-r--r--src/mongo/db/ftdc/ftdc_mongos.h43
-rw-r--r--src/mongo/db/ftdc/ftdc_server.cpp350
-rw-r--r--src/mongo/db/ftdc/ftdc_server.h103
-rw-r--r--src/mongo/db/ftdc/ftdc_system_stats.h1
-rw-r--r--src/mongo/db/ftdc/util.cpp13
-rw-r--r--src/mongo/db/ftdc/util.h5
-rw-r--r--src/mongo/db/ftdc/util_test.cpp21
17 files changed, 804 insertions, 352 deletions
diff --git a/src/mongo/db/ftdc/SConscript b/src/mongo/db/ftdc/SConscript
index 0d16aec93f2..81df9ad0f4d 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,44 @@ 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.Library(
+ target='ftdc_mongos',
+ source=[
+ 'ftdc_mongos.cpp',
+ ],
+ LIBDEPS=[
+ 'ftdc_server'
+ ],
+)
+
env.CppUnitTest(
target='ftdc_test',
source=[
diff --git a/src/mongo/db/ftdc/collector.cpp b/src/mongo/db/ftdc/collector.cpp
index 611f12dff5a..7c35fb12bb6 100644
--- a/src/mongo/db/ftdc/collector.cpp
+++ b/src/mongo/db/ftdc/collector.cpp
@@ -67,6 +67,7 @@ std::tuple<BSONObj, Date_t> FTDCCollectorCollection::collect(Client* client) {
// batches that are taking a long time.
auto txn = client->makeOperationContext();
txn->lockState()->setShouldConflictWithSecondaryBatchApplication(false);
+ txn->lockState()->setShouldAcquireTicket(false);
for (auto& collector : _collectors) {
BSONObjBuilder subObjBuilder(builder.subobjStart(collector->name()));
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/controller.cpp b/src/mongo/db/ftdc/controller.cpp
index 9e2987db0f9..bc3d4df444c 100644
--- a/src/mongo/db/ftdc/controller.cpp
+++ b/src/mongo/db/ftdc/controller.cpp
@@ -47,9 +47,19 @@
namespace mongo {
-void FTDCController::setEnabled(bool enabled) {
+Status FTDCController::setEnabled(bool enabled) {
stdx::lock_guard<stdx::mutex> lock(_mutex);
+
+ if (_path.empty()) {
+ return Status(ErrorCodes::FTDCPathNotSet,
+ str::stream() << "FTDC cannot be enabled without setting the set parameter "
+ "'diagnosticDataCollectionDirectoryPath' first.");
+ }
+
_configTemp.enabled = enabled;
+ _condvar.notify_one();
+
+ return Status::OK();
}
void FTDCController::setPeriod(Milliseconds millis) {
@@ -82,6 +92,23 @@ void FTDCController::setMaxSamplesPerInterimMetricChunk(size_t size) {
_condvar.notify_one();
}
+Status FTDCController::setDirectory(const boost::filesystem::path& path) {
+ stdx::lock_guard<stdx::mutex> lock(_mutex);
+
+ if (!_path.empty()) {
+ return Status(ErrorCodes::FTDCPathAlreadySet,
+ str::stream() << "FTDC path has already been set to '" << _path.string()
+ << "'. It cannot be changed.");
+ }
+
+ _path = path;
+
+ // Do not notify for the change since it has to be enabled via setEnabled.
+
+ return Status::OK();
+}
+
+
void FTDCController::addPeriodicCollector(std::unique_ptr<FTDCCollectorInterface> collector) {
{
stdx::lock_guard<stdx::mutex> lock(_mutex);
@@ -203,7 +230,7 @@ void FTDCController::doLoop() {
}
// TODO: consider only running this thread if we are enabled
- // for now, we just keep an idle thread as it is simplier
+ // for now, we just keep an idle thread as it is simpler
if (_config.enabled) {
// Delay initialization of FTDCFileManager until we are sure the user has enabled
// FTDC
diff --git a/src/mongo/db/ftdc/controller.h b/src/mongo/db/ftdc/controller.h
index 44b5e838506..e73d570598d 100644
--- a/src/mongo/db/ftdc/controller.h
+++ b/src/mongo/db/ftdc/controller.h
@@ -62,8 +62,12 @@ public:
/*
* Set whether the controller is enabled, and collects data.
+ *
+ * Returns ErrorCodes::FTDCPathNotSet if no log path has been specified for FTDC. This occurs
+ * in MongoS in some situations since MongoS is not required to have a storage directory like
+ * MongoD does.
*/
- void setEnabled(bool enabled);
+ Status setEnabled(bool enabled);
/**
* Set the period for data collection.
@@ -94,6 +98,13 @@ public:
*/
void setMaxSamplesPerInterimMetricChunk(size_t size);
+ /*
+ * Set the path to store FTDC files if not already set.
+ *
+ * Returns ErrorCodes::FTDCPathAlreadySet if the path has already been set.
+ */
+ Status setDirectory(const boost::filesystem::path& path);
+
/**
* Add a metric collector to collect periodically. i.e., serverStatus
*/
@@ -172,7 +183,7 @@ private:
State _state{State::kNotStarted};
// Directory to store files
- const boost::filesystem::path _path;
+ boost::filesystem::path _path;
// Mutex to protect the condvar, configuration changes, and most recent periodic document.
stdx::mutex _mutex;
diff --git a/src/mongo/db/ftdc/controller_test.cpp b/src/mongo/db/ftdc/controller_test.cpp
index 365f06580cd..c75a3fe44d6 100644
--- a/src/mongo/db/ftdc/controller_test.cpp
+++ b/src/mongo/db/ftdc/controller_test.cpp
@@ -254,7 +254,7 @@ TEST(FTDCControllerTest, TestStartAsDisabled) {
ASSERT_EQUALS(files0.size(), 0UL);
- c.setEnabled(true);
+ ASSERT_OK(c.setEnabled(true));
c1Ptr->setSignalOnCount(50);
diff --git a/src/mongo/db/ftdc/ftdc_mongod.cpp b/src/mongo/db/ftdc/ftdc_mongod.cpp
index 094a2b05d06..1f53ec345ea 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, FTDCStartMode::kStart, 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_mongos.cpp b/src/mongo/db/ftdc/ftdc_mongos.cpp
new file mode 100644
index 00000000000..bdacaa7b6e1
--- /dev/null
+++ b/src/mongo/db/ftdc/ftdc_mongos.cpp
@@ -0,0 +1,153 @@
+/**
+ * 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.
+ */
+#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kFTDC
+
+#include "mongo/platform/basic.h"
+
+#include "mongo/db/ftdc/ftdc_mongos.h"
+
+#include <boost/filesystem.hpp>
+
+#include "mongo/db/ftdc/controller.h"
+#include "mongo/db/ftdc/ftdc_server.h"
+#include "mongo/db/server_parameters.h"
+#include "mongo/stdx/thread.h"
+#include "mongo/util/log.h"
+
+namespace mongo {
+
+namespace {
+
+/**
+ * Expose diagnosticDataCollectionDirectoryPath set parameter to specify the MongoS FTDC path.
+ */
+class ExportedFTDCDirectoryPathParameter : public ServerParameter {
+public:
+ ExportedFTDCDirectoryPathParameter()
+ : ServerParameter(ServerParameterSet::getGlobal(),
+ "diagnosticDataCollectionDirectoryPath",
+ true,
+ true) {}
+
+
+ void append(OperationContext* opCtx, BSONObjBuilder& b, const std::string& name) final {
+ stdx::lock_guard<stdx::mutex> guard(_lock);
+ b.append(name, _path.generic_string());
+ }
+
+ Status set(const BSONElement& newValueElement) {
+ if (newValueElement.type() != String) {
+ return Status(ErrorCodes::BadValue,
+ "diagnosticDataCollectionDirectoryPath only supports type string");
+ }
+
+ std::string str = newValueElement.str();
+ return setFromString(str);
+ }
+
+ Status setFromString(const std::string& str) final {
+ stdx::lock_guard<stdx::mutex> guard(_lock);
+
+ FTDCController* controller = nullptr;
+
+ if (hasGlobalServiceContext()) {
+ controller = FTDCController::get(getGlobalServiceContext());
+ }
+
+ if (controller) {
+ Status s = controller->setDirectory(str);
+ if (!s.isOK()) {
+ return s;
+ }
+ }
+
+ _path = str;
+
+ return Status::OK();
+ }
+
+ boost::filesystem::path getDirectory() {
+ stdx::lock_guard<stdx::mutex> guard(_lock);
+ return _path;
+ }
+
+ void setDirectory(boost::filesystem::path& path) {
+ stdx::lock_guard<stdx::mutex> guard(_lock);
+ _path = path;
+ }
+
+private:
+ // Lock to guard _path
+ stdx::mutex _lock;
+
+ // Directory location of ftdc files, guarded by _lock
+ boost::filesystem::path _path;
+} exportedFTDCDirectoryPathParameter;
+
+void registerMongoSCollectors(FTDCController* controller) {
+ // PoolStats
+ controller->addPeriodicCollector(stdx::make_unique<FTDCSimpleInternalCommandCollector>(
+ "connPoolStats", "connPoolStats", "", BSON("connPoolStats" << 1)));
+}
+
+} // namespace
+
+void startMongoSFTDC() {
+ // Get the path to use for FTDC:
+ // 1. Check if the user set one.
+ // 2. If not, check if the user has a logpath and derive one.
+ // 3. Otherwise, tell the user FTDC cannot run.
+
+ // Only attempt to enable FTDC if we have a path to log files to.
+ FTDCStartMode startMode = FTDCStartMode::kStart;
+ auto directory = exportedFTDCDirectoryPathParameter.getDirectory();
+
+ if (directory.empty()) {
+ if (serverGlobalParams.logpath.empty()) {
+ warning() << "FTDC is disabled because neither '--logpath' nor set parameter "
+ "'diagnosticDataCollectionDirectoryPath' are specified.";
+ startMode = FTDCStartMode::kSkipStart;
+ } else {
+ directory = FTDCUtil::getMongoSPath(serverGlobalParams.logpath);
+
+ // Update the server parameter with the computed path.
+ // Note: If the computed FTDC directory conflicts with an existing file, then FTDC will
+ // warn about the conflict, and not startup. It will not terminate MongoS in this
+ // situation.
+ exportedFTDCDirectoryPathParameter.setDirectory(directory);
+ }
+ }
+
+ startFTDC(directory, startMode, registerMongoSCollectors);
+}
+
+void stopMongoSFTDC() {
+ stopFTDC();
+}
+
+} // namespace mongo
diff --git a/src/mongo/db/ftdc/ftdc_mongos.h b/src/mongo/db/ftdc/ftdc_mongos.h
new file mode 100644
index 00000000000..4d8ff8fc08b
--- /dev/null
+++ b/src/mongo/db/ftdc/ftdc_mongos.h
@@ -0,0 +1,43 @@
+/**
+ * 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
+
+namespace mongo {
+
+/**
+ * Start Full Time Data Capture
+ */
+void startMongoSFTDC();
+
+/**
+ * Stop Full Time Data Capture
+ */
+void stopMongoSFTDC();
+
+} // 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..167587a8722
--- /dev/null
+++ b/src/mongo/db/ftdc/ftdc_server.cpp
@@ -0,0 +1,350 @@
+/**
+ * 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) {
+ return 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,
+ FTDCStartMode startupMode,
+ RegisterCollectorsFunction registerCollectors) {
+ FTDCConfig config;
+ config.period = Milliseconds(localPeriodMillis.load());
+ // Only enable FTDC if our caller says to enable FTDC, MongoS may not have a valid path to write
+ // files to so update the diagnosticDataCollectionEnabled set parameter to reflect that.
+ localEnabledFlag.store(startupMode == FTDCStartMode::kStart && localEnabledFlag.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..4b4583ae153
--- /dev/null
+++ b/src/mongo/db/ftdc/ftdc_server.h
@@ -0,0 +1,103 @@
+/**
+ * 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*)>;
+
+/**
+ * An enum that decides whether FTDC will startup as part of startup or if its deferred to later.
+ */
+enum class FTDCStartMode {
+
+ /**
+ * Skip starting FTDC since it missing a file storage location.
+ */
+ kSkipStart,
+
+ /**
+ * Start FTDC because it has a path to store files.
+ */
+ kStart,
+};
+
+/**
+ * Start Full Time Data Capture
+ * Starts 1 thread.
+ *
+ * See MongoD and MongoS specific functions.
+ */
+void startFTDC(boost::filesystem::path& path,
+ FTDCStartMode startupMode,
+ 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>
diff --git a/src/mongo/db/ftdc/util.cpp b/src/mongo/db/ftdc/util.cpp
index d56eb8ca380..243ba90b666 100644
--- a/src/mongo/db/ftdc/util.cpp
+++ b/src/mongo/db/ftdc/util.cpp
@@ -103,6 +103,19 @@ Date_t roundTime(Date_t now, Milliseconds period) {
return Date_t::fromMillisSinceEpoch(next_time);
}
+boost::filesystem::path getMongoSPath(const boost::filesystem::path& logFile) {
+ auto base = logFile;
+
+ // Keep stripping file extensions until we are only left with the file name
+ while (base.has_extension()) {
+ auto full_path = base.generic_string();
+ base = full_path.substr(0, full_path.size() - base.extension().size());
+ }
+
+ base += "." + kFTDCDefaultDirectory.toString();
+ return base;
+}
+
} // namespace FTDCUtil
diff --git a/src/mongo/db/ftdc/util.h b/src/mongo/db/ftdc/util.h
index 0cb4d19ce7f..4816c534f96 100644
--- a/src/mongo/db/ftdc/util.h
+++ b/src/mongo/db/ftdc/util.h
@@ -190,6 +190,11 @@ boost::filesystem::path getInterimTempFile(const boost::filesystem::path& file);
*/
Date_t roundTime(Date_t now, Milliseconds period);
+/**
+ * Get the storage path for MongoS from the log file path.
+ */
+boost::filesystem::path getMongoSPath(const boost::filesystem::path& logFile);
+
} // namespace FTDCUtil
} // namespace mongo
diff --git a/src/mongo/db/ftdc/util_test.cpp b/src/mongo/db/ftdc/util_test.cpp
index aa99006c73a..0adf0f73c15 100644
--- a/src/mongo/db/ftdc/util_test.cpp
+++ b/src/mongo/db/ftdc/util_test.cpp
@@ -46,4 +46,25 @@ TEST(FTDCUtilTest, TestRoundTime) {
checkTime(14, 13, 7);
}
+// Validate the MongoS FTDC path is computed correctly from a log file path.
+TEST(FTDCUtilTest, TestMongoSPath) {
+
+ std::vector<std::pair<std::string, std::string>> testCases = {
+ {"/var/log/mongos.log", "/var/log/mongos.diagnostic.data"},
+ {"/var/log/mongos.foo.log", "/var/log/mongos.diagnostic.data"},
+ {"/var/log/log_file", "/var/log/log_file.diagnostic.data"},
+ {"./mongos.log", "./mongos.diagnostic.data"},
+ {"../mongos.log", "../mongos.diagnostic.data"},
+ {"c:\\var\\log\\mongos.log", "c:\\var\\log\\mongos.diagnostic.data"},
+ {"c:\\var\\log\\mongos.foo.log", "c:\\var\\log\\mongos.diagnostic.data"},
+ {"c:\\var\\log\\log_file", "c:\\var\\log\\log_file.diagnostic.data"},
+ {"/var/some.log/mongos.log", "/var/some.log/mongos.diagnostic.data"},
+ {"/var/some.log/log_file", "/var/some.log/log_file.diagnostic.data"},
+ };
+
+ for (const auto& p : testCases) {
+ ASSERT_EQUALS(FTDCUtil::getMongoSPath(p.first), p.second);
+ }
+}
+
} // namespace mongo