diff options
author | Sara Golemon <sara.golemon@mongodb.com> | 2020-08-28 17:02:46 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-10-21 17:26:58 +0000 |
commit | 78a269596edf46413b8533132d10da995953d5ee (patch) | |
tree | 399988b9e42bac0c299fa8a913c5e2f413a16e69 /src/mongo | |
parent | 8d91cd9f7887b3b2c44243b6230e676f32fb37a2 (diff) | |
download | mongo-78a269596edf46413b8533132d10da995953d5ee.tar.gz |
SERVER-50605 Add logMessage test-only command
Based on:
(cherry picked from commit 273cba82968bab5316b5f937875757a12f363626)
Refactored to accomodate logv1
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/db/commands/generic.cpp | 41 | ||||
-rw-r--r-- | src/mongo/db/initialize_server_global_state.cpp | 1 | ||||
-rw-r--r-- | src/mongo/embedded/mongo_embedded/mongo_embedded_test.cpp | 1 | ||||
-rw-r--r-- | src/mongo/logger/logstream_builder.cpp | 2 | ||||
-rw-r--r-- | src/mongo/logger/logstream_builder.h | 66 |
5 files changed, 99 insertions, 12 deletions
diff --git a/src/mongo/db/commands/generic.cpp b/src/mongo/db/commands/generic.cpp index 786084fe6ac..8090acbe864 100644 --- a/src/mongo/db/commands/generic.cpp +++ b/src/mongo/db/commands/generic.cpp @@ -192,5 +192,46 @@ public: } listCommandsCmd; +class CmdLogMessage : public BasicCommand { +public: + CmdLogMessage() : BasicCommand("logMessage") {} + + std::string help() const final { + return "Send a message to the server log"; + } + + bool supportsWriteConcern(const BSONObj& cmd) const final { + return false; + } + + AllowedOnSecondary secondaryAllowed(ServiceContext*) const final { + return AllowedOnSecondary::kAlways; + } + + bool adminOnly() const final { + return true; + } + + void addRequiredPrivileges(const std::string& dbname, + const BSONObj& cmdObj, + std::vector<Privilege>* out) const final { + out->push_back( + Privilege(ResourcePattern::forClusterResource(), ActionType::applicationMessage)); + } + + bool run(OperationContext* opCtx, + const std::string& ns, + const BSONObj& cmdObj, + BSONObjBuilder& result) final { + auto msgElem = cmdObj["logMessage"]; + uassert(ErrorCodes::BadValue, "logMessage must be a string", msgElem.type() == String); + + log() << "logMessage: " << msgElem.valueStringData(); + return true; + } +}; + +MONGO_REGISTER_TEST_COMMAND(CmdLogMessage); + } // namespace } // namespace mongo diff --git a/src/mongo/db/initialize_server_global_state.cpp b/src/mongo/db/initialize_server_global_state.cpp index 05c90bb7a65..9607b566dd2 100644 --- a/src/mongo/db/initialize_server_global_state.cpp +++ b/src/mongo/db/initialize_server_global_state.cpp @@ -313,6 +313,7 @@ MONGO_INITIALIZER_GENERAL( logger::globalLogDomain()->attachAppender( std::make_unique<RamLogAppender>(RamLog::get("global"))); + logger::LogstreamBuilder::setNewlineEscape(); return Status::OK(); } diff --git a/src/mongo/embedded/mongo_embedded/mongo_embedded_test.cpp b/src/mongo/embedded/mongo_embedded/mongo_embedded_test.cpp index c4db59d99cb..3a52cc81f5c 100644 --- a/src/mongo/embedded/mongo_embedded/mongo_embedded_test.cpp +++ b/src/mongo/embedded/mongo_embedded/mongo_embedded_test.cpp @@ -579,6 +579,7 @@ TEST_F(MongodbCAPITest, RunListCommands) { "listDatabases", "listIndexes", "lockInfo", + "logMessage", "ping", "planCacheClear", "planCacheClearFilters", diff --git a/src/mongo/logger/logstream_builder.cpp b/src/mongo/logger/logstream_builder.cpp index d21b50e49e8..5f64e7be51f 100644 --- a/src/mongo/logger/logstream_builder.cpp +++ b/src/mongo/logger/logstream_builder.cpp @@ -70,6 +70,8 @@ struct ThreadOstreamCacheFinalizer { namespace logger { +bool LogstreamBuilder::newlineEscape = false; + LogstreamBuilder::LogstreamBuilder(MessageLogDomain* domain, StringData contextName, LogSeverity severity) diff --git a/src/mongo/logger/logstream_builder.h b/src/mongo/logger/logstream_builder.h index 2ea07987521..176663e573a 100644 --- a/src/mongo/logger/logstream_builder.h +++ b/src/mongo/logger/logstream_builder.h @@ -115,24 +115,19 @@ public: } LogstreamBuilder& operator<<(const char* x) { - stream() << x; - return *this; + return appendEscapedString(x); } LogstreamBuilder& operator<<(const std::string& x) { - stream() << x; - return *this; + return appendEscapedString(x); } LogstreamBuilder& operator<<(StringData x) { - stream() << x; - return *this; + return appendEscapedString(x); } LogstreamBuilder& operator<<(char* x) { - stream() << x; - return *this; + return appendEscapedString(x); } LogstreamBuilder& operator<<(char x) { - stream() << x; - return *this; + return appendEscapedChar(x); } LogstreamBuilder& operator<<(int x) { stream() << x; @@ -201,8 +196,7 @@ public: template <typename T> LogstreamBuilder& operator<<(const T& x) { - stream() << x.toString(); - return *this; + return appendEscapedString(x.toString()); } LogstreamBuilder& operator<<(std::ostream& (*manip)(std::ostream&)) { @@ -230,9 +224,57 @@ public: */ void operator<<(Tee* tee); + /** + * Enable newilne escaping behavior. + */ + static void setNewlineEscape() { + newlineEscape = true; + } + private: + /** + * Global option to escape newlines. + */ + static bool newlineEscape; + void makeStream(); + // Append a string explicitly escaping \r and \n only. + LogstreamBuilder& appendEscapedString(StringData x) { + if (newlineEscape) { + auto idx = std::min(x.find('\r'), x.find('\n')); + while (idx != std::string::npos) { + if (idx > 0) { + stream() << x.substr(0, idx); + } + appendEscapedChar(x[idx]); + x = x.substr(idx + 1); + idx = std::min(x.find('\r'), x.find('\n')); + } + } + + stream() << x; + return *this; + } + + LogstreamBuilder& appendEscapedChar(char ch) { + if (newlineEscape) { + switch (ch) { + case '\n': + stream() << "\\n"; + break; + case '\r': + stream() << "\\r"; + break; + default: + stream() << ch; + } + } else { + stream() << ch; + } + return *this; + } + MessageLogDomain* _domain; std::string _contextName; LogSeverity _severity; |