summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenrik Edin <henrik.edin@mongodb.com>2019-10-30 19:54:36 +0000
committerevergreen <evergreen@mongodb.com>2019-10-30 19:54:36 +0000
commit384d11c0ee81c524873eaa999122dc61320226ea (patch)
tree6654cf8e3e5d9602b2ca45595ceac48b233cfb46
parentdde6a5946c185a4432e846f884b36e9aad2e06a8 (diff)
downloadmongo-384d11c0ee81c524873eaa999122dc61320226ea.tar.gz
SERVER-44277 Add capability for shell to use logv2
-rw-r--r--src/mongo/logger/log_version_util.h54
-rw-r--r--src/mongo/logger/logv2_appender.h21
-rw-r--r--src/mongo/logv2/text_formatter.h2
-rw-r--r--src/mongo/shell/dbshell.cpp86
-rw-r--r--src/mongo/shell/shell_options.cpp4
-rw-r--r--src/mongo/shell/shell_options.h2
-rw-r--r--src/mongo/shell/shell_options.idl5
7 files changed, 160 insertions, 14 deletions
diff --git a/src/mongo/logger/log_version_util.h b/src/mongo/logger/log_version_util.h
new file mode 100644
index 00000000000..ba60ba37477
--- /dev/null
+++ b/src/mongo/logger/log_version_util.h
@@ -0,0 +1,54 @@
+/**
+ * Copyright (C) 2018-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * 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
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * 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 Server Side 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 "mongo/logger/log_component.h"
+#include "mongo/logger/log_severity.h"
+#include "mongo/logv2/log_component.h"
+#include "mongo/logv2/log_severity.h"
+
+namespace mongo {
+inline logv2::LogComponent logComponentV1toV2(logger::LogComponent component) {
+ return logv2::LogComponent(static_cast<logv2::LogComponent::Value>(
+ static_cast<std::underlying_type_t<logger::LogComponent::Value>>(
+ static_cast<logger::LogComponent::Value>(component))));
+}
+inline logger::LogComponent logComponentV2toV1(logv2::LogComponent component) {
+ return logger::LogComponent(static_cast<logger::LogComponent::Value>(
+ static_cast<std::underlying_type_t<logv2::LogComponent::Value>>(
+ static_cast<logv2::LogComponent::Value>(component))));
+}
+inline logv2::LogSeverity logSeverityV1toV2(logger::LogSeverity severity) {
+ return logv2::LogSeverity::cast(severity.toInt());
+}
+inline logger::LogSeverity logSeverityV2toV1(logv2::LogSeverity severity) {
+ return logger::LogSeverity::cast(severity.toInt());
+}
+} // namespace mongo \ No newline at end of file
diff --git a/src/mongo/logger/logv2_appender.h b/src/mongo/logger/logv2_appender.h
index ef79823b7ec..67567ea1af1 100644
--- a/src/mongo/logger/logv2_appender.h
+++ b/src/mongo/logger/logv2_appender.h
@@ -31,6 +31,7 @@
#include "mongo/base/status.h"
#include "mongo/logger/appender.h"
+#include "mongo/logger/log_version_util.h"
#include "mongo/logv2/attribute_argument_set.h"
#include "mongo/logv2/log_component.h"
#include "mongo/logv2/log_detail.h"
@@ -67,7 +68,8 @@ public:
LogV2Appender(const LogV2Appender&) = delete;
LogV2Appender& operator=(const LogV2Appender&) = delete;
- explicit LogV2Appender(logv2::LogDomain* domain) : _domain(domain) {}
+ explicit LogV2Appender(logv2::LogDomain* domain, logv2::LogTag extraTag = logv2::LogTag::kNone)
+ : _domain(domain), _tag(extraTag) {}
Status append(const Event& event) override {
@@ -83,20 +85,21 @@ public:
// Similarly, we need to transcode the options. They don't offer a cast
// operator, so we need to do some metaprogramming on the types.
- logv2::LogOptions{logv2::LogComponent(static_cast<logv2::LogComponent::Value>(
- static_cast<std::underlying_type_t<LogComponent::Value>>(
- static_cast<LogComponent::Value>(event.getComponent())))),
- _domain,
- logv2::LogTag{logTagValue}},
-
- "{} {}", // TODO remove this lv2 when it's no longer fun to have
- "engine"_attr = "lv2",
+ logv2::LogOptions{
+ logComponentV1toV2(event.getComponent()),
+ _domain,
+ logv2::LogTag{static_cast<logv2::LogTag::Value>(
+ static_cast<std::underlying_type_t<logv2::LogTag::Value>>(logTagValue) |
+ static_cast<std::underlying_type_t<logv2::LogTag::Value>>(_tag))}},
+
+ "{}",
"message"_attr = event.getMessage());
return Status::OK();
}
private:
logv2::LogDomain* _domain;
+ logv2::LogTag _tag;
};
} // namespace logger
diff --git a/src/mongo/logv2/text_formatter.h b/src/mongo/logv2/text_formatter.h
index bd213d0972f..501897e0f69 100644
--- a/src/mongo/logv2/text_formatter.h
+++ b/src/mongo/logv2/text_formatter.h
@@ -89,7 +89,7 @@ public:
strm.write(_buffer.data(), _buffer.size());
}
-private:
+protected:
fmt::memory_buffer _buffer;
};
diff --git a/src/mongo/shell/dbshell.cpp b/src/mongo/shell/dbshell.cpp
index b923ffc1fa7..3b65e2fb68b 100644
--- a/src/mongo/shell/dbshell.cpp
+++ b/src/mongo/shell/dbshell.cpp
@@ -31,7 +31,11 @@
#include "mongo/platform/basic.h"
+#include <boost/core/null_deleter.hpp>
#include <boost/filesystem/operations.hpp>
+#include <boost/log/attributes/value_extraction.hpp>
+#include <boost/log/core.hpp>
+#include <boost/log/sinks.hpp>
#include <cctype>
#include <fstream>
#include <iostream>
@@ -51,7 +55,15 @@
#include "mongo/db/server_options.h"
#include "mongo/logger/console_appender.h"
#include "mongo/logger/logger.h"
+#include "mongo/logger/logv2_appender.h"
#include "mongo/logger/message_event_utf8_encoder.h"
+#include "mongo/logv2/attribute_argument_set.h"
+#include "mongo/logv2/attributes.h"
+#include "mongo/logv2/component_settings_filter.h"
+#include "mongo/logv2/console.h"
+#include "mongo/logv2/log_domain_global.h"
+#include "mongo/logv2/log_manager.h"
+#include "mongo/logv2/text_formatter.h"
#include "mongo/platform/atomic_word.h"
#include "mongo/scripting/engine.h"
#include "mongo/shell/linenoise.h"
@@ -122,6 +134,7 @@ const auto kAuthParam = "authSource"s;
*/
class ShellConsoleAppender final : public logger::ConsoleAppender<logger::MessageEventEphemeral> {
using Base = logger::ConsoleAppender<logger::MessageEventEphemeral>;
+ friend class ShellBackend;
public:
using Base::Base;
@@ -162,6 +175,41 @@ private:
static inline bool loggingEnabled = true;
};
+/**
+ * Logv2 equivalent of ShellConsoleAppender above. Sharing the lock and LoggingDisabledScope.
+ */
+class ShellBackend final : public boost::log::sinks::text_ostream_backend {
+public:
+ void consume(boost::log::record_view const& rec, string_type const& formatted_message) {
+ auto lk = stdx::lock_guard(ShellConsoleAppender::mx);
+ if (!ShellConsoleAppender::loggingEnabled)
+ return;
+ boost::log::sinks::text_ostream_backend::consume(rec, formatted_message);
+ }
+};
+
+/**
+ * Formatter to provide specialized formatting for logs from javascript engine
+ */
+class ShellFormatter final : private logv2::TextFormatter {
+public:
+ void operator()(boost::log::record_view const& rec, boost::log::formatting_ostream& strm) {
+ using namespace logv2;
+ using boost::log::extract;
+
+ if (extract<LogTag>(attributes::tags(), rec).get().has(LogTag::kJavascript)) {
+ StringData message = extract<StringData>(attributes::message(), rec).get();
+ const auto& attrs = extract<AttributeArgumentSet>(attributes::attributes(), rec).get();
+
+ _buffer.clear();
+ fmt::internal::vformat_to(_buffer, to_string_view(message), attrs._values);
+ strm.write(_buffer.data(), _buffer.size());
+ } else {
+ logv2::TextFormatter::operator()(rec, strm);
+ }
+ }
+};
+
} // namespace
namespace mongo {
@@ -677,6 +725,12 @@ int _main(int argc, char* argv[], char** envp) {
logger::globalLogManager()->getGlobalDomain()->attachAppender(
std::make_unique<ShellConsoleAppender>(
std::make_unique<logger::MessageEventDetailsEncoder>()));
+
+ auto& lv2Manager = logv2::LogManager::global();
+ logv2::LogDomainGlobal::ConfigurationOptions lv2Config;
+ lv2Config.makeDisabled();
+ uassertStatusOK(lv2Manager.getGlobalDomainInternal().configure(lv2Config));
+
mongo::shell_utils::RecordMyLocation(argv[0]);
mongo::runGlobalInitializersOrDie(argc, argv, envp);
@@ -701,10 +755,34 @@ int _main(int argc, char* argv[], char** envp) {
if (!mongo::serverGlobalParams.quiet.load())
std::cout << mongoShellVersion(VersionInfoInterface::instance()) << std::endl;
- logger::globalLogManager()
- ->getNamedDomain("javascriptOutput")
- ->attachAppender(std::make_unique<ShellConsoleAppender>(
- std::make_unique<logger::MessageEventUnadornedEncoder>()));
+ if (!shellGlobalParams.logV2) {
+ logger::globalLogManager()
+ ->getNamedDomain("javascriptOutput")
+ ->attachAppender(std::make_unique<ShellConsoleAppender>(
+ std::make_unique<logger::MessageEventUnadornedEncoder>()));
+ } else {
+ logger::globalLogManager()->getGlobalDomain()->clearAppenders();
+ logger::globalLogManager()->getGlobalDomain()->attachAppender(
+ std::make_unique<logger::LogV2Appender<logger::MessageEventEphemeral>>(
+ &(lv2Manager.getGlobalDomain())));
+ logger::globalLogManager()
+ ->getNamedDomain("javascriptOutput")
+ ->attachAppender(std::make_unique<logger::LogV2Appender<logger::MessageEventEphemeral>>(
+ &lv2Manager.getGlobalDomain(), logv2::LogTag::kJavascript));
+
+ auto consoleSink = boost::make_shared<boost::log::sinks::synchronous_sink<ShellBackend>>();
+ consoleSink->set_filter(logv2::ComponentSettingsFilter(lv2Manager.getGlobalDomain(),
+ lv2Manager.getGlobalSettings()));
+ consoleSink->set_formatter(ShellFormatter());
+
+ consoleSink->locked_backend()->add_stream(
+ boost::shared_ptr<std::ostream>(&logv2::Console::out(), boost::null_deleter()));
+
+ consoleSink->locked_backend()->auto_flush();
+
+ boost::log::core::get()->add_sink(std::move(consoleSink));
+ }
+
// Get the URL passed to the shell
std::string& cmdlineURI = shellGlobalParams.url;
diff --git a/src/mongo/shell/shell_options.cpp b/src/mongo/shell/shell_options.cpp
index 1d6ab03990e..2441ff9ce45 100644
--- a/src/mongo/shell/shell_options.cpp
+++ b/src/mongo/shell/shell_options.cpp
@@ -337,6 +337,10 @@ Status storeMongoShellOptions(const moe::Environment& params,
}
}
+ if (params.count("logv2")) {
+ shellGlobalParams.logV2 = true;
+ }
+
return Status::OK();
}
diff --git a/src/mongo/shell/shell_options.h b/src/mongo/shell/shell_options.h
index 45ac4e55455..2868998197f 100644
--- a/src/mongo/shell/shell_options.h
+++ b/src/mongo/shell/shell_options.h
@@ -81,6 +81,8 @@ struct ShellGlobalParams {
int jsHeapLimitMB = 0;
bool nokillop = false;
Seconds idleSessionTimeout = Seconds{0};
+
+ bool logV2 = false;
};
extern ShellGlobalParams shellGlobalParams;
diff --git a/src/mongo/shell/shell_options.idl b/src/mongo/shell/shell_options.idl
index dc66354e25e..c56a951b2ee 100644
--- a/src/mongo/shell/shell_options.idl
+++ b/src/mongo/shell/shell_options.idl
@@ -208,3 +208,8 @@ configs:
arg_vartype: Int
default: 0
validator: {gte: 0}
+
+ "logv2":
+ description: "logging gets directed to the logv2 backend"
+ arg_vartype: Switch
+ source: [ cli, ini ]