diff options
author | Ian Whalen <ian.whalen@gmail.com> | 2017-09-21 10:20:20 -0400 |
---|---|---|
committer | Ian Whalen <ian.whalen@gmail.com> | 2017-09-21 10:20:20 -0400 |
commit | 0e3c8a96af7f9ddd6d5a059c92f6303eba1d0b32 (patch) | |
tree | 8b92add4f9b8a2a9ca939f93656ecac9781d03cb | |
parent | 48cdb7d69246339e097bf23ec0e6b9187a3f9221 (diff) | |
download | mongo-0e3c8a96af7f9ddd6d5a059c92f6303eba1d0b32.tar.gz |
Revert "SERVER-21677 Remove "diaglog" support from the server"
This reverts commit d5d61785d59f62e29ba01843f8c15cf08a5ca55a.
-rw-r--r-- | debian/mongod.1 | 86 | ||||
-rw-r--r-- | debian/mongosniff.1 | 200 | ||||
-rw-r--r-- | jstests/auth/lib/commands_lib.js | 14 | ||||
-rw-r--r-- | jstests/core/views/views_all_commands.js | 1 | ||||
-rw-r--r-- | jstests/sharding/safe_secondary_reads_drop_recreate.js | 1 | ||||
-rw-r--r-- | jstests/sharding/safe_secondary_reads_single_migration_suspend_range_deletion.js | 1 | ||||
-rw-r--r-- | jstests/sharding/safe_secondary_reads_single_migration_waitForDelete.js | 1 | ||||
-rw-r--r-- | src/mongo/db/SConscript | 13 | ||||
-rw-r--r-- | src/mongo/db/auth/action_types.txt | 1 | ||||
-rw-r--r-- | src/mongo/db/auth/role_graph_builtin_roles.cpp | 1 | ||||
-rw-r--r-- | src/mongo/db/commands/dbcommands.cpp | 59 | ||||
-rw-r--r-- | src/mongo/db/db.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/diag_log.cpp | 109 | ||||
-rw-r--r-- | src/mongo/db/diag_log.h | 65 | ||||
-rw-r--r-- | src/mongo/db/mongod_options.cpp | 16 | ||||
-rw-r--r-- | src/mongo/db/service_entry_point_mongod.cpp | 21 | ||||
-rw-r--r-- | src/mongo/db/storage/mmap_v1/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/storage/mmap_v1/data_file_sync.cpp | 2 |
18 files changed, 596 insertions, 0 deletions
diff --git a/debian/mongod.1 b/debian/mongod.1 index 7982e554870..b775b7004d5 100644 --- a/debian/mongod.1 +++ b/debian/mongod.1 @@ -232,6 +232,92 @@ _ .UNINDENT .INDENT 0.0 .TP +.B \-\-diaglog <value> +\fIDefault\fP: 0 +.sp +Deprecated since version 2.6. + +.sp +\fI\%\-\-diaglog\fP is for internal use and not intended for most users. +.sp +Creates a very verbose \fIdiagnostic log\fP for troubleshooting and +recording various errors. MongoDB writes these log files in the +\fBdbPath\fP directory in a series of files that begin with the +string \fBdiaglog\fP and end with the initiation time of the logging as a +hex string. +.sp +The specified value configures the level of verbosity: +.TS +center; +|l|l|. +_ +T{ +Value +T} T{ +Setting +T} +_ +T{ +0 +T} T{ +Off. No logging. +T} +_ +T{ +1 +T} T{ +Log write operations. +T} +_ +T{ +2 +T} T{ +Log read operations. +T} +_ +T{ +3 +T} T{ +Log both read and write operations. +T} +_ +T{ +7 +T} T{ +Log write and some read operations. +T} +_ +.TE +.sp +You can use the \fBmongosniff\fP tool to replay this output for +investigation. Given a typical diaglog file located at +\fB/data/db/diaglog.4f76a58c\fP, you might use a command in the following +form to read these files: +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C +mongosniff \-\-source DIAGLOG /data/db/diaglog.4f76a58c +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +\fBWARNING:\fP +.INDENT 7.0 +.INDENT 3.5 +Setting the diagnostic level to \fB0\fP will cause \fBmongod\fP +to stop writing data to the \fIdiagnostic log\fP file. However, +the \fBmongod\fP instance will continue to keep the file open, +even if it is no longer writing data to the file. If you want to +rename, move, or delete the diagnostic log you must cleanly shut +down the \fBmongod\fP instance before doing so. +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP .B \-\-traceExceptions For internal diagnostic use only. .UNINDENT diff --git a/debian/mongosniff.1 b/debian/mongosniff.1 new file mode 100644 index 00000000000..600a792c3df --- /dev/null +++ b/debian/mongosniff.1 @@ -0,0 +1,200 @@ +.\" Man page generated from reStructuredText. +. +.TH "MONGOSNIFF" "1" "January 30, 2015" "3.0" "mongodb-manual" +.SH NAME +mongosniff \- MongoDB Protocol Introspection Utility +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.SH SYNOPSIS +.sp +\fBmongosniff\fP provides a low\-level operation tracing/sniffing view +into database activity in real time. Think of \fBmongosniff\fP as a +MongoDB\-specific analogue of \fBtcpdump\fP for TCP/IP network +traffic. Typically, \fBmongosniff\fP is most frequently used in driver +development. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +\fBmongosniff\fP requires \fBlibpcap\fP and is only available for +Unix\-like systems. +.UNINDENT +.UNINDENT +.sp +As an alternative to \fBmongosniff\fP, Wireshark, a popular +network sniffing tool is capable of inspecting and parsing the MongoDB +wire protocol. +.SH OPTIONS +.INDENT 0.0 +.TP +.B mongosniff +.UNINDENT +.INDENT 0.0 +.TP +.B mongosniff +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-help +Returns information on the options and use of \fBmongosniff\fP\&. +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-forward <host><:port> +Declares a host to forward all parsed requests that the +\fBmongosniff\fP intercepts to another \fBmongod\fP instance +and issue those operations on that database instance. +.sp +Specify the target host name and port in the \fB<host><:port>\fP format. +.sp +To connect to a replica set, specify the \fBreplica set name\fP and a seed list of set members. Use the +following form: +.INDENT 7.0 +.INDENT 3.5 +.sp +.nf +.ft C +<replSetName>/<hostname1><:port>,<hostname2><:port>,<...> +.ft P +.fi +.UNINDENT +.UNINDENT +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-source <NET [interface]> +Specifies source material to inspect. Use \fB\-\-source NET [interface]\fP +to inspect traffic from a network interface (e.g. \fBeth0\fP or \fBlo\fP\&.) +Use \fB\-\-source FILE [filename]\fP to read captured packets in +\fIpcap\fP format. +.sp +You may use the \fB\-\-source DIAGLOG [filename]\fP option to read the +output files produced by the \fI\-\-diaglog\fP +option. +.UNINDENT +.INDENT 0.0 +.TP +.B \-\-objcheck +Displays invalid BSON objects only and nothing else. Use this option for +troubleshooting driver development. This option has some performance +impact on the performance of \fBmongosniff\fP\&. +.UNINDENT +.INDENT 0.0 +.TP +.B <port> +Specifies alternate ports to sniff for traffic. By default, +\fBmongosniff\fP watches for MongoDB traffic on port \fB27017\fP\&. Append +multiple port numbers to the end of \fBmongosniff\fP to monitor +traffic on multiple ports. +.UNINDENT +.SH USE +.sp +Use the following command to connect to a \fBmongod\fP or +\fBmongos\fP running on port 27017 \fIand\fP 27018 on the localhost +interface: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +mongosniff \-\-source NET lo 27017 27018 +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +Use the following command to only log invalid \fIBSON\fP objects for +the \fBmongod\fP or \fBmongos\fP running on the localhost +interface and port 27018, for driver development and troubleshooting: +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +mongosniff \-\-objcheck \-\-source NET lo 27018 +.ft P +.fi +.UNINDENT +.UNINDENT +.SH BUILD MONGOSNIFF +.sp +To build \fBmongosniff\fP yourself, Linux users can use the following +procedure: +.INDENT 0.0 +.IP 1. 3 +Obtain prerequisites using your operating +systems package management software. Dependencies include: +.INDENT 3.0 +.IP \(bu 2 +\fBlibpcap\fP \- to capture network packets. +.IP \(bu 2 +\fBgit\fP \- to download the MongoDB source code. +.IP \(bu 2 +\fBscons\fP and a C++ compiler \- to build \fBmongosniff\fP\&. +.UNINDENT +.IP 2. 3 +Download a copy of the MongoDB source code using \fBgit\fP: +.INDENT 3.0 +.INDENT 3.5 +.sp +.nf +.ft C +git clone git://github.com/mongodb/mongo.git +.ft P +.fi +.UNINDENT +.UNINDENT +.IP 3. 3 +Issue the following sequence of commands to change to the +\fBmongo/\fP directory and build \fBmongosniff\fP: +.INDENT 3.0 +.INDENT 3.5 +.sp +.nf +.ft C +cd mongo +scons mongosniff +.ft P +.fi +.UNINDENT +.UNINDENT +.UNINDENT +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +If you run \fBscons mongosniff\fP before installing \fBlibpcap\fP you +must run \fBscons clean\fP before you can build \fBmongosniff\fP\&. +.UNINDENT +.UNINDENT +.SH AUTHOR +MongoDB Documentation Project +.SH COPYRIGHT +2011-2015 +.\" Generated by docutils manpage writer. +. diff --git a/jstests/auth/lib/commands_lib.js b/jstests/auth/lib/commands_lib.js index 90b8d1051f8..077ed4fe388 100644 --- a/jstests/auth/lib/commands_lib.js +++ b/jstests/auth/lib/commands_lib.js @@ -2246,6 +2246,20 @@ var authCommandsLib = { ] }, { + testname: "diagLogging", + command: {diagLogging: 1}, + skipSharded: true, + testcases: [ + { + runOnDb: adminDbName, + roles: roles_hostManager, + privileges: [{resource: {cluster: true}, actions: ["diagLogging"]}] + }, + {runOnDb: firstDbName, roles: {}}, + {runOnDb: secondDbName, roles: {}} + ] + }, + { testname: "distinct", command: {distinct: "coll", key: "a", query: {}}, testcases: [ diff --git a/jstests/core/views/views_all_commands.js b/jstests/core/views/views_all_commands.js index ff5842be316..b56d61fe7a7 100644 --- a/jstests/core/views/views_all_commands.js +++ b/jstests/core/views/views_all_commands.js @@ -180,6 +180,7 @@ }, dbStats: {skip: "TODO(SERVER-25948)"}, delete: {command: {delete: "view", deletes: [{q: {x: 1}, limit: 1}]}, expectFailure: true}, + diagLogging: {skip: isUnrelated}, distinct: {command: {distinct: "view", key: "_id"}}, driverOIDTest: {skip: isUnrelated}, drop: {command: {drop: "view"}}, diff --git a/jstests/sharding/safe_secondary_reads_drop_recreate.js b/jstests/sharding/safe_secondary_reads_drop_recreate.js index 488906bef52..5b49fd1dc24 100644 --- a/jstests/sharding/safe_secondary_reads_drop_recreate.js +++ b/jstests/sharding/safe_secondary_reads_drop_recreate.js @@ -132,6 +132,7 @@ dbHash: {skip: "does not return user data"}, dbStats: {skip: "does not return user data"}, delete: {skip: "primary only"}, + diagLogging: {skip: "does not return user data"}, distinct: { setUp: function(mongosConn) { assert.writeOK(mongosConn.getCollection(nss).insert({x: 1})); diff --git a/jstests/sharding/safe_secondary_reads_single_migration_suspend_range_deletion.js b/jstests/sharding/safe_secondary_reads_single_migration_suspend_range_deletion.js index ccb774e5f8f..44ac466c435 100644 --- a/jstests/sharding/safe_secondary_reads_single_migration_suspend_range_deletion.js +++ b/jstests/sharding/safe_secondary_reads_single_migration_suspend_range_deletion.js @@ -151,6 +151,7 @@ dbHash: {skip: "does not return user data"}, dbStats: {skip: "does not return user data"}, delete: {skip: "primary only"}, + diagLogging: {skip: "does not return user data"}, distinct: { setUp: function(mongosConn) { assert.writeOK(mongosConn.getCollection(nss).insert({x: 1})); diff --git a/jstests/sharding/safe_secondary_reads_single_migration_waitForDelete.js b/jstests/sharding/safe_secondary_reads_single_migration_waitForDelete.js index 98713affc78..bf09aebe9f5 100644 --- a/jstests/sharding/safe_secondary_reads_single_migration_waitForDelete.js +++ b/jstests/sharding/safe_secondary_reads_single_migration_waitForDelete.js @@ -134,6 +134,7 @@ dbHash: {skip: "does not return user data"}, dbStats: {skip: "does not return user data"}, delete: {skip: "primary only"}, + diagLogging: {skip: "does not return user data"}, distinct: { setUp: function(mongosConn) { assert.writeOK(mongosConn.getCollection(nss).insert({x: 1})); diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript index cf2b8e6cd7f..e63c3b20742 100644 --- a/src/mongo/db/SConscript +++ b/src/mongo/db/SConscript @@ -413,6 +413,7 @@ env.Library( ], LIBDEPS=[ '$BUILD_DIR/mongo/db/storage/mmap_v1/mmap_v1_options', + 'diag_log', 'repl/repl_settings', 'server_options', 'storage/storage_options', @@ -591,6 +592,7 @@ env.Library( 'concurrency/lock_manager', 'curop', 'curop_metrics', + 'diag_log', 'lasterror', 'ops/write_ops_parsers', 'rw_concern_d', @@ -755,6 +757,16 @@ env.Library( ) env.Library( + target="diag_log", + source=[ + "diag_log.cpp", + ], + LIBDEPS=[ + "storage/storage_options", + ], +) + +env.Library( target="authz_manager_external_state_factory_d", source=[ "authz_manager_external_state_factory_d.cpp", @@ -806,6 +818,7 @@ env.Library( "db_raii", "dbdirectclient", "dbhelpers", + "diag_log", "exec/exec", "exec/working_set", "ftdc/ftdc_mongod", diff --git a/src/mongo/db/auth/action_types.txt b/src/mongo/db/auth/action_types.txt index 1f57ba6084b..2fdb27bbeb0 100644 --- a/src/mongo/db/auth/action_types.txt +++ b/src/mongo/db/auth/action_types.txt @@ -34,6 +34,7 @@ "createUser", "dbHash", "dbStats", +"diagLogging", "dropAllRolesFromDatabase", # Not used for permissions checks, but to id the event in logs. "dropAllUsersFromDatabase", # Not used for permissions checks, but to id the event in logs. "dropCollection", diff --git a/src/mongo/db/auth/role_graph_builtin_roles.cpp b/src/mongo/db/auth/role_graph_builtin_roles.cpp index 47ba56ce752..d79149c368d 100644 --- a/src/mongo/db/auth/role_graph_builtin_roles.cpp +++ b/src/mongo/db/auth/role_graph_builtin_roles.cpp @@ -213,6 +213,7 @@ MONGO_INITIALIZER(AuthorizationBuiltinRoles)(InitializerContext* context) { << ActionType::shutdown << ActionType::touch << ActionType::unlock + << ActionType::diagLogging << ActionType::flushRouterConfig // clusterManager gets this also << ActionType::fsync << ActionType::invalidateUserCache // userAdminAnyDatabase gets this also diff --git a/src/mongo/db/commands/dbcommands.cpp b/src/mongo/db/commands/dbcommands.cpp index 15851760bc5..791d851c376 100644 --- a/src/mongo/db/commands/dbcommands.cpp +++ b/src/mongo/db/commands/dbcommands.cpp @@ -64,6 +64,7 @@ #include "mongo/db/db_raii.h" #include "mongo/db/dbdirectclient.h" #include "mongo/db/dbhelpers.h" +#include "mongo/db/diag_log.h" #include "mongo/db/exec/working_set_common.h" #include "mongo/db/index/index_access_method.h" #include "mongo/db/index/index_descriptor.h" @@ -390,6 +391,64 @@ public: } cmdProfile; +class CmdDiagLogging : public BasicCommand { +public: + virtual bool slaveOk() const { + return true; + } + CmdDiagLogging() : BasicCommand("diagLogging") {} + bool adminOnly() const { + return true; + } + + void help(stringstream& h) const { + h << "http://dochub.mongodb.org/core/" + "monitoring#MonitoringandDiagnostics-DatabaseRecord%2FReplay%28diagLoggingcommand%29"; + } + + + virtual bool supportsWriteConcern(const BSONObj& cmd) const override { + return false; + } + + virtual void addRequiredPrivileges(const std::string& dbname, + const BSONObj& cmdObj, + std::vector<Privilege>* out) { + ActionSet actions; + actions.addAction(ActionType::diagLogging); + out->push_back(Privilege(ResourcePattern::forClusterResource(), actions)); + } + + bool run(OperationContext* opCtx, + const string& dbname, + const BSONObj& cmdObj, + BSONObjBuilder& result) { + const char* deprecationWarning = + "CMD diagLogging is deprecated and will be removed in a future release"; + warning() << deprecationWarning << startupWarningsLog; + + // This doesn't look like it requires exclusive DB lock, because it uses its own diag + // locking, but originally the lock was set to be WRITE, so preserving the behaviour. + Lock::DBLock dbXLock(opCtx, dbname, MODE_X); + + // TODO (Kal): OldClientContext legacy, needs to be removed + { + CurOp::get(opCtx)->ensureStarted(); + stdx::lock_guard<Client> lk(*opCtx->getClient()); + CurOp::get(opCtx)->setNS_inlock(dbname); + } + + int was = _diaglog.setLevel(cmdObj.firstElement().numberInt()); + _diaglog.flush(); + if (!serverGlobalParams.quiet.load()) { + LOG(0) << "CMD: diagLogging set to " << _diaglog.getLevel() << " from: " << was; + } + result.append("was", was); + result.append("note", deprecationWarning); + return true; + } +} cmddiaglogging; + /* drop collection */ class CmdDrop : public ErrmsgCommandDeprecated { public: diff --git a/src/mongo/db/db.cpp b/src/mongo/db/db.cpp index ef1e073e1db..7bef30a8593 100644 --- a/src/mongo/db/db.cpp +++ b/src/mongo/db/db.cpp @@ -65,6 +65,7 @@ #include "mongo/db/dbdirectclient.h" #include "mongo/db/dbhelpers.h" #include "mongo/db/dbmessage.h" +#include "mongo/db/diag_log.h" #include "mongo/db/exec/working_set_common.h" #include "mongo/db/ftdc/ftdc_mongod.h" #include "mongo/db/index_names.h" @@ -1012,6 +1013,9 @@ void shutdownTask() { log(LogComponent::kNetwork) << "shutdown: going to close listening sockets..."; ListeningSockets::get()->closeAll(); + log(LogComponent::kNetwork) << "shutdown: going to flush diaglog..."; + _diaglog.flush(); + if (serviceContext->getGlobalStorageEngine()) { ServiceContext::UniqueOperationContext uniqueOpCtx; OperationContext* opCtx = client->getOperationContext(); diff --git a/src/mongo/db/diag_log.cpp b/src/mongo/db/diag_log.cpp new file mode 100644 index 00000000000..9b4606d478f --- /dev/null +++ b/src/mongo/db/diag_log.cpp @@ -0,0 +1,109 @@ +/** + * Copyright (C) 2008-2014 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::kDefault; + +#include "mongo/platform/basic.h" + +#include <fstream> +#include <iomanip> +#include <sstream> + +#include "mongo/db/diag_log.h" + +#include "mongo/db/storage/storage_options.h" +#include "mongo/util/assert_util.h" +#include "mongo/util/log.h" + +namespace mongo { + +using std::hex; +using std::ios; +using std::ofstream; +using std::string; +using std::stringstream; + +DiagLog::DiagLog() : f(0), level(0) {} + +void DiagLog::openFile() { + verify(f == 0); + stringstream ss; + ss << storageGlobalParams.dbpath << "/diaglog." << hex << time(0); + string name = ss.str(); + f = new ofstream(name.c_str(), ios::out | ios::binary); + if (!f->good()) { + str::stream msg; + msg << "diagLogging couldn't open " << name; + log() << msg.ss.str(); + uasserted(ErrorCodes::FileStreamFailed, msg.ss.str()); + } else { + log() << "diagLogging using file " << name; + } +} + +int DiagLog::setLevel(int newLevel) { + stdx::lock_guard<stdx::mutex> lk(mutex); + int old = level; + log() << "diagLogging level=" << newLevel; + if (f == 0) { + openFile(); + } + level = newLevel; // must be done AFTER f is set + return old; +} + +void DiagLog::flush() { + if (level) { + log() << "flushing diag log"; + stdx::lock_guard<stdx::mutex> lk(mutex); + f->flush(); + } +} + +void DiagLog::writeop(char* data, int len) { + if (level & 1) { + stdx::lock_guard<stdx::mutex> lk(mutex); + f->write(data, len); + } +} + +void DiagLog::readop(char* data, int len) { + if (level & 2) { + bool log = (level & 4) == 0; + OCCASIONALLY log = true; + if (log) { + stdx::lock_guard<stdx::mutex> lk(mutex); + verify(f); + f->write(data, len); + } + } +} + +DiagLog _diaglog; + +} // namespace mongo diff --git a/src/mongo/db/diag_log.h b/src/mongo/db/diag_log.h new file mode 100644 index 00000000000..739f15aec43 --- /dev/null +++ b/src/mongo/db/diag_log.h @@ -0,0 +1,65 @@ +/** +* Copyright (C) 2008 10gen 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 <iosfwd> + +#include "mongo/stdx/mutex.h" + +namespace mongo { + +/** a high level recording of operations to the database - sometimes used for diagnostics + and debugging. + */ +class DiagLog { + std::ofstream* f; // note this is never freed + /* 0 = off; 1 = writes, 2 = reads, 3 = both + 7 = log a few reads, and all writes. + */ + int level; + stdx::mutex mutex; + void openFile(); + +public: + DiagLog(); + int getLevel() const { + return level; + } + /** + * @return old + */ + int setLevel(int newLevel); + void flush(); + void writeop(char* data, int len); + void readop(char* data, int len); +}; + +extern DiagLog _diaglog; + +} // namespace mongo diff --git a/src/mongo/db/mongod_options.cpp b/src/mongo/db/mongod_options.cpp index 7e31a8f2890..ae7407bbd6a 100644 --- a/src/mongo/db/mongod_options.cpp +++ b/src/mongo/db/mongod_options.cpp @@ -40,6 +40,7 @@ #include "mongo/bson/util/builder.h" #include "mongo/config.h" #include "mongo/db/db.h" +#include "mongo/db/diag_log.h" #include "mongo/db/repl/repl_settings.h" #include "mongo/db/server_options.h" #include "mongo/db/server_options_helpers.h" @@ -132,6 +133,12 @@ Status addMongodOptions(moe::OptionSection* options) { // Diagnostic Options general_options + .addOptionChaining( + "diaglog", "diaglog", moe::Int, "DEPRECATED: 0=off 1=W 2=R 3=both 7=W+some reads") + .hidden() + .setSources(moe::SourceAllLegacy); + + general_options .addOptionChaining("operationProfiling.slowOpThresholdMs", "slowms", moe::Int, @@ -1069,6 +1076,15 @@ Status storeMongodOptions(const moe::Environment& params) { if (params.count("storage.mmapv1.smallFiles")) { mmapv1GlobalOptions.smallfiles = params["storage.mmapv1.smallFiles"].as<bool>(); } + if (params.count("diaglog")) { + warning() << "--diaglog is deprecated and will be removed in a future release" + << startupWarningsLog; + int x = params["diaglog"].as<int>(); + if (x < 0 || x > 7) { + return Status(ErrorCodes::BadValue, "can't interpret --diaglog setting"); + } + _diaglog.setLevel(x); + } if ((params.count("storage.journal.enabled") && params["storage.journal.enabled"].as<bool>() == true) && diff --git a/src/mongo/db/service_entry_point_mongod.cpp b/src/mongo/db/service_entry_point_mongod.cpp index dfec6d0382b..1e24a469a1d 100644 --- a/src/mongo/db/service_entry_point_mongod.cpp +++ b/src/mongo/db/service_entry_point_mongod.cpp @@ -44,6 +44,7 @@ #include "mongo/db/curop_metrics.h" #include "mongo/db/cursor_manager.h" #include "mongo/db/dbdirectclient.h" +#include "mongo/db/diag_log.h" #include "mongo/db/initialize_operation_session_info.h" #include "mongo/db/introspect.h" #include "mongo/db/jsobj.h" @@ -106,6 +107,18 @@ const StringMap<int> cmdWhitelist = {{"delete", 1}, {"refreshLogicalSessionCacheNow", 1}, {"update", 1}}; +inline void opread(const Message& m) { + if (_diaglog.getLevel() & 2) { + _diaglog.readop(m.singleData().view2ptr(), m.header().getLen()); + } +} + +inline void opwrite(const Message& m) { + if (_diaglog.getLevel() & 1) { + _diaglog.writeop(m.singleData().view2ptr(), m.header().getLen()); + } +} + void generateLegacyQueryErrorResponse(const AssertionException* exception, const QueryMessage& queryMessage, CurOp* curop, @@ -1068,9 +1081,17 @@ DbResponse ServiceEntryPointMongod::handleRequest(OperationContext* opCtx, const if (op == dbQuery) { if (nsString.isCommand()) { isCommand = true; + opwrite(m); + } else { + opread(m); } + } else if (op == dbGetMore) { + opread(m); } else if (op == dbCommand || op == dbMsg) { isCommand = true; + opwrite(m); + } else { + opwrite(m); } CurOp& currentOp = *CurOp::get(opCtx); diff --git a/src/mongo/db/storage/mmap_v1/SConscript b/src/mongo/db/storage/mmap_v1/SConscript index 0e308816953..a1642bc578a 100644 --- a/src/mongo/db/storage/mmap_v1/SConscript +++ b/src/mongo/db/storage/mmap_v1/SConscript @@ -69,6 +69,7 @@ env.Library( '$BUILD_DIR/mongo/db/commands', '$BUILD_DIR/mongo/db/commands/server_status', '$BUILD_DIR/mongo/db/concurrency/lock_manager', + '$BUILD_DIR/mongo/db/diag_log', '$BUILD_DIR/mongo/db/index_names', '$BUILD_DIR/mongo/db/index/index_descriptor', '$BUILD_DIR/mongo/db/storage/journal_listener', diff --git a/src/mongo/db/storage/mmap_v1/data_file_sync.cpp b/src/mongo/db/storage/mmap_v1/data_file_sync.cpp index 4d895c09b20..ab7dca95ff9 100644 --- a/src/mongo/db/storage/mmap_v1/data_file_sync.cpp +++ b/src/mongo/db/storage/mmap_v1/data_file_sync.cpp @@ -34,6 +34,7 @@ #include "mongo/db/client.h" #include "mongo/db/commands/server_status_metric.h" +#include "mongo/db/diag_log.h" #include "mongo/db/operation_context.h" #include "mongo/db/service_context.h" #include "mongo/db/storage/mmap_v1/dur_journal.h" @@ -65,6 +66,7 @@ void DataFileSync::run() { } int time_flushing = 0; while (!globalInShutdownDeprecated()) { + _diaglog.flush(); if (storageGlobalParams.syncdelay == 0) { // in case at some point we add an option to change at runtime sleepsecs(5); |