diff options
author | Mark Benvenuto <mark.benvenuto@mongodb.com> | 2017-06-30 15:19:38 -0400 |
---|---|---|
committer | Mark Benvenuto <mark.benvenuto@mongodb.com> | 2018-03-12 15:46:23 -0400 |
commit | 2b8d573e40fe26b9285a053ed3b7a8e62f68c2e2 (patch) | |
tree | 1cd45d923371e36d88e02cf672b3b47fc244b2df | |
parent | c3860652ccb14862b132d95df4f034230c7423e1 (diff) | |
download | mongo-2b8d573e40fe26b9285a053ed3b7a8e62f68c2e2.tar.gz |
SERVER-29938 FTDC Refactor
(cherry picked from commit 4d8405a45c7be94f1022ae3d3de4731e2bf9632b)
-rw-r--r-- | src/mongo/db/db.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/ftdc/SConscript | 21 | ||||
-rw-r--r-- | src/mongo/db/ftdc/compressor_test.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/ftdc/constants.h | 6 | ||||
-rw-r--r-- | src/mongo/db/ftdc/ftdc_mongod.cpp | 323 | ||||
-rw-r--r-- | src/mongo/db/ftdc/ftdc_mongod.h | 56 | ||||
-rw-r--r-- | src/mongo/db/ftdc/ftdc_server.cpp | 343 | ||||
-rw-r--r-- | src/mongo/db/ftdc/ftdc_server.h | 85 | ||||
-rw-r--r-- | src/mongo/db/ftdc/ftdc_system_stats.h | 1 |
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> |