diff options
author | Henrik Edin <henrik.edin@mongodb.com> | 2019-10-30 19:54:36 +0000 |
---|---|---|
committer | evergreen <evergreen@mongodb.com> | 2019-10-30 19:54:36 +0000 |
commit | 384d11c0ee81c524873eaa999122dc61320226ea (patch) | |
tree | 6654cf8e3e5d9602b2ca45595ceac48b233cfb46 | |
parent | dde6a5946c185a4432e846f884b36e9aad2e06a8 (diff) | |
download | mongo-384d11c0ee81c524873eaa999122dc61320226ea.tar.gz |
SERVER-44277 Add capability for shell to use logv2
-rw-r--r-- | src/mongo/logger/log_version_util.h | 54 | ||||
-rw-r--r-- | src/mongo/logger/logv2_appender.h | 21 | ||||
-rw-r--r-- | src/mongo/logv2/text_formatter.h | 2 | ||||
-rw-r--r-- | src/mongo/shell/dbshell.cpp | 86 | ||||
-rw-r--r-- | src/mongo/shell/shell_options.cpp | 4 | ||||
-rw-r--r-- | src/mongo/shell/shell_options.h | 2 | ||||
-rw-r--r-- | src/mongo/shell/shell_options.idl | 5 |
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 ] |