Skip to content

Commit 81e1eb0

Browse files
Gabriel Russellevergreen
authored andcommitted
SERVER-43746 logv2 Tee and RamLog
1 parent 9bee42b commit 81e1eb0

File tree

9 files changed

+108
-46
lines changed

9 files changed

+108
-46
lines changed

src/mongo/db/commands/generic_servers.cpp

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "mongo/db/commands/shutdown.h"
3838
#include "mongo/db/commands/test_commands_enabled.h"
3939
#include "mongo/db/log_process_details.h"
40+
#include "mongo/logv2/ramlog.h"
4041
#include "mongo/scripting/engine.h"
4142
#include "mongo/util/exit.h"
4243
#include "mongo/util/fail_point.h"
@@ -52,9 +53,6 @@
5253
namespace mongo {
5354
namespace {
5455

55-
using std::string;
56-
using std::vector;
57-
5856
class FeaturesCmd : public BasicCommand {
5957
public:
6058
FeaturesCmd() : BasicCommand("features") {}
@@ -71,7 +69,7 @@ class FeaturesCmd : public BasicCommand {
7169
const BSONObj& cmdObj,
7270
std::vector<Privilege>* out) const {} // No auth required
7371
virtual bool run(OperationContext* opCtx,
74-
const string& ns,
72+
const std::string& ns,
7573
const BSONObj& cmdObj,
7674
BSONObjBuilder& result) {
7775
if (getGlobalScriptEngine()) {
@@ -112,7 +110,7 @@ class HostInfoCmd : public BasicCommand {
112110
out->push_back(Privilege(ResourcePattern::forClusterResource(), actions));
113111
}
114112
bool run(OperationContext* opCtx,
115-
const string& dbname,
113+
const std::string& dbname,
116114
const BSONObj& cmdObj,
117115
BSONObjBuilder& result) {
118116
ProcessInfo p;
@@ -165,7 +163,7 @@ class CmdGetCmdLineOpts : public BasicCommand {
165163
out->push_back(Privilege(ResourcePattern::forClusterResource(), actions));
166164
}
167165
virtual bool run(OperationContext* opCtx,
168-
const string&,
166+
const std::string&,
169167
const BSONObj& cmdObj,
170168
BSONObjBuilder& result) {
171169
result.append("argv", serverGlobalParams.argvArray);
@@ -195,7 +193,7 @@ class LogRotateCmd : public BasicCommand {
195193
out->push_back(Privilege(ResourcePattern::forClusterResource(), actions));
196194
}
197195
virtual bool run(OperationContext* opCtx,
198-
const string& ns,
196+
const std::string& ns,
199197
const BSONObj& cmdObj,
200198
BSONObjBuilder& result) {
201199
bool didRotate = rotateLogs(serverGlobalParams.logRenameOnRotate, serverGlobalParams.logV2);
@@ -230,22 +228,34 @@ class GetLogCmd : public ErrmsgCommandDeprecated {
230228
return "{ getLog : '*' } OR { getLog : 'global' }";
231229
}
232230

233-
virtual bool errmsgRun(OperationContext* opCtx,
234-
const string& dbname,
235-
const BSONObj& cmdObj,
236-
string& errmsg,
237-
BSONObjBuilder& result) {
231+
bool errmsgRun(OperationContext* opCtx,
232+
const std::string& dbname,
233+
const BSONObj& cmdObj,
234+
std::string& errmsg,
235+
BSONObjBuilder& result) override {
236+
if (serverGlobalParams.logV2) {
237+
return errmsgRunImpl<logv2::RamLog>(opCtx, dbname, cmdObj, errmsg, result);
238+
}
239+
return errmsgRunImpl<RamLog>(opCtx, dbname, cmdObj, errmsg, result);
240+
}
241+
242+
template <typename RamLogType>
243+
bool errmsgRunImpl(OperationContext* opCtx,
244+
const std::string& dbname,
245+
const BSONObj& cmdObj,
246+
std::string& errmsg,
247+
BSONObjBuilder& result) {
238248
BSONElement val = cmdObj.firstElement();
239249
if (val.type() != String) {
240250
uasserted(ErrorCodes::TypeMismatch,
241251
str::stream() << "Argument to getLog must be of type String; found "
242252
<< val.toString(false) << " of type " << typeName(val.type()));
243253
}
244254

245-
string p = val.String();
255+
std::string p = val.String();
246256
if (p == "*") {
247-
vector<string> names;
248-
RamLog::getNames(names);
257+
std::vector<std::string> names;
258+
RamLogType::getNames(names);
249259

250260
BSONArrayBuilder arr;
251261
for (unsigned i = 0; i < names.size(); i++) {
@@ -254,12 +264,12 @@ class GetLogCmd : public ErrmsgCommandDeprecated {
254264

255265
result.appendArray("names", arr.arr());
256266
} else {
257-
RamLog* ramlog = RamLog::getIfExists(p);
267+
RamLogType* ramlog = RamLogType::getIfExists(p);
258268
if (!ramlog) {
259269
errmsg = str::stream() << "no RamLog named: " << p;
260270
return false;
261271
}
262-
RamLog::LineIterator rl(ramlog);
272+
typename RamLogType::LineIterator rl(ramlog);
263273

264274
result.appendNumber("totalLinesWritten", rl.getTotalLinesWritten());
265275

@@ -298,7 +308,7 @@ class ClearLogCmd : public BasicCommand {
298308
}
299309

300310
virtual bool run(OperationContext* opCtx,
301-
const string& dbname,
311+
const std::string& dbname,
302312
const BSONObj& cmdObj,
303313
BSONObjBuilder& result) {
304314
std::string logName;
@@ -308,9 +318,15 @@ class ClearLogCmd : public BasicCommand {
308318
if (logName != "global") {
309319
uasserted(ErrorCodes::InvalidOptions, "Only the 'global' log can be cleared");
310320
}
311-
RamLog* ramlog = RamLog::getIfExists(logName);
312-
invariant(ramlog);
313-
ramlog->clear();
321+
auto clearRamlog = [&](auto* ramlog) {
322+
invariant(ramlog);
323+
ramlog->clear();
324+
};
325+
if (serverGlobalParams.logV2) {
326+
clearRamlog(logv2::RamLog::getIfExists(logName));
327+
} else {
328+
clearRamlog(RamLog::getIfExists(logName));
329+
}
314330
return true;
315331
}
316332
};

src/mongo/db/commands/server_status.cpp

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
#include "mongo/util/log.h"
4141
#include "mongo/util/net/http_client.h"
4242
#include "mongo/util/net/socket_utils.h"
43-
#include "mongo/util/ramlog.h"
4443
#include "mongo/util/version.h"
4544

4645
namespace mongo {
@@ -142,18 +141,6 @@ class CmdServerStatus : public BasicCommand {
142141

143142
// --- some hard coded global things hard to pull out
144143

145-
{
146-
RamLog::LineIterator rl(RamLog::get("warnings"));
147-
if (rl.lastWrite() >=
148-
time(nullptr) - (10 * 60)) { // only show warnings from last 10 minutes
149-
BSONArrayBuilder arr(result.subarrayStart("warnings"));
150-
while (rl.more()) {
151-
arr.append(rl.next());
152-
}
153-
arr.done();
154-
}
155-
}
156-
157144
auto runElapsed = clock->now() - runStart;
158145
timeBuilder.appendNumber("at end", durationCount<Milliseconds>(runElapsed));
159146
if (runElapsed > Milliseconds(1000)) {

src/mongo/db/initialize_server_global_state.cpp

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -231,10 +231,13 @@ MONGO_INITIALIZER_GENERAL(ServerLogRedirection,
231231
"Syslog requested in Windows build; command line processor logic error");
232232
#else
233233
std::unique_ptr<logger::Appender<MessageEventEphemeral>> appender;
234+
std::unique_ptr<logger::Appender<MessageEventEphemeral>> javascriptAppender;
234235

235236
if (serverGlobalParams.logV2) {
236237
appender = std::make_unique<logger::LogV2Appender<MessageEventEphemeral>>(
237238
&(lv2Manager.getGlobalDomain()));
239+
javascriptAppender = std::make_unique<logger::LogV2Appender<MessageEventEphemeral>>(
240+
&(lv2Manager.getGlobalDomain()));
238241

239242
lv2Config._consoleEnabled = false;
240243
lv2Config._syslogEnabled = true;
@@ -246,13 +249,13 @@ MONGO_INITIALIZER_GENERAL(ServerLogRedirection,
246249
openlog(
247250
strdup(sb.str().c_str()), LOG_PID | LOG_CONS, serverGlobalParams.syslogFacility);
248251
appender = std::make_unique<SyslogAppender<MessageEventEphemeral>>(
249-
std::make_unique<logger::MessageEventDetailsEncoder>());
250-
manager->getNamedDomain("javascriptOutput")
251-
->attachAppender(std::make_unique<SyslogAppender<MessageEventEphemeral>>(
252-
std::make_unique<logger::MessageEventDetailsEncoder>()));
252+
std::make_unique<MessageEventDetailsEncoder>());
253+
javascriptAppender = std::make_unique<SyslogAppender<MessageEventEphemeral>>(
254+
std::make_unique<MessageEventDetailsEncoder>());
253255
}
254256
manager->getGlobalDomain()->clearAppenders();
255257
manager->getGlobalDomain()->attachAppender(std::move(appender));
258+
manager->getNamedDomain("javascriptOutput")->attachAppender(std::move(javascriptAppender));
256259

257260
#endif // defined(_WIN32)
258261
} else if (!serverGlobalParams.logpath.empty()) {
@@ -297,11 +300,14 @@ MONGO_INITIALIZER_GENERAL(ServerLogRedirection,
297300
}
298301

299302
std::unique_ptr<logger::Appender<MessageEventEphemeral>> appender;
303+
std::unique_ptr<logger::Appender<MessageEventEphemeral>> javascriptAppender;
300304

301305
if (serverGlobalParams.logV2) {
302306

303307
appender = std::make_unique<logger::LogV2Appender<MessageEventEphemeral>>(
304308
&(lv2Manager.getGlobalDomain()));
309+
javascriptAppender = std::make_unique<logger::LogV2Appender<MessageEventEphemeral>>(
310+
&(lv2Manager.getGlobalDomain()));
305311

306312
lv2Config._consoleEnabled = false;
307313
lv2Config._fileEnabled = true;
@@ -329,9 +335,8 @@ MONGO_INITIALIZER_GENERAL(ServerLogRedirection,
329335
}
330336
appender = std::make_unique<RotatableFileAppender<MessageEventEphemeral>>(
331337
std::make_unique<MessageEventDetailsEncoder>(), writer.getValue());
332-
manager->getNamedDomain("javascriptOutput")
333-
->attachAppender(std::make_unique<RotatableFileAppender<MessageEventEphemeral>>(
334-
std::make_unique<MessageEventDetailsEncoder>(), writer.getValue()));
338+
javascriptAppender = std::make_unique<RotatableFileAppender<MessageEventEphemeral>>(
339+
std::make_unique<MessageEventDetailsEncoder>(), writer.getValue());
335340
if (serverGlobalParams.logAppend && exists) {
336341
log() << "***** SERVER RESTARTED *****";
337342
Status status = logger::RotatableFileWriter::Use(writer.getValue()).status();
@@ -342,23 +347,29 @@ MONGO_INITIALIZER_GENERAL(ServerLogRedirection,
342347

343348
manager->getGlobalDomain()->clearAppenders();
344349
manager->getGlobalDomain()->attachAppender(std::move(appender));
350+
manager->getNamedDomain("javascriptOutput")->attachAppender(std::move(javascriptAppender));
345351

346352
} else {
347353
if (serverGlobalParams.logV2) {
348354
manager->getGlobalDomain()->clearAppenders();
349355
manager->getGlobalDomain()->attachAppender(
350356
std::make_unique<logger::LogV2Appender<MessageEventEphemeral>>(
351357
&(lv2Manager.getGlobalDomain())));
358+
manager->getNamedDomain("javascriptOutput")
359+
->attachAppender(std::make_unique<logger::LogV2Appender<MessageEventEphemeral>>(
360+
&(lv2Manager.getGlobalDomain())));
352361
} else {
353362
logger::globalLogManager()
354363
->getNamedDomain("javascriptOutput")
355364
->attachAppender(std::make_unique<logger::ConsoleAppender<MessageEventEphemeral>>(
356365
std::make_unique<MessageEventDetailsEncoder>()));
357366
}
358367
}
368+
if (!serverGlobalParams.logV2) {
369+
logger::globalLogDomain()->attachAppender(
370+
std::make_unique<RamLogAppender>(RamLog::get("global")));
371+
}
359372

360-
logger::globalLogDomain()->attachAppender(
361-
std::make_unique<RamLogAppender>(RamLog::get("global")));
362373

363374
if (serverGlobalParams.logV2) {
364375
lv2Config._format = serverGlobalParams.logFormat;

src/mongo/logger/logstream_builder.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,11 @@
3333

3434
#include <memory>
3535

36+
#include "mongo/base/checked_cast.h"
3637
#include "mongo/base/init.h"
3738
#include "mongo/base/status.h"
3839
#include "mongo/logger/message_event_utf8_encoder.h"
40+
#include "mongo/logger/ramlog.h"
3941
#include "mongo/logger/tee.h"
4042
#include "mongo/util/assert_util.h" // TODO: remove apple dep for this in threadlocal.h
4143
#include "mongo/util/time_support.h"
@@ -94,6 +96,9 @@ LogstreamBuilder::~LogstreamBuilder() {
9496
MessageEventEphemeral message(
9597
Date_t::now(), _severity, _component, _contextName, _baseMessage);
9698
message.setIsTruncatable(_isTruncatable);
99+
if (_tee) {
100+
message.setTeeName(checked_cast<RamLog*>(_tee)->getName());
101+
}
97102
_domain->append(message).transitional_ignore();
98103
if (_tee) {
99104
_os->str("");

src/mongo/logger/logv2_appender.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,29 @@
3535
#include "mongo/logv2/log_component.h"
3636
#include "mongo/logv2/log_detail.h"
3737
#include "mongo/logv2/log_domain.h"
38+
#include "mongo/logv2/log_tag.h"
3839

3940
namespace mongo {
4041
namespace logger {
4142

43+
44+
namespace {
45+
46+
auto findTeeTag(StringData teeName) {
47+
static constexpr std::pair<StringData, logv2::LogTag::Value> kTees[] = {
48+
{"rs"_sd, logv2::LogTag::kRS},
49+
{"startupWarnings"_sd, logv2::LogTag::kStartupWarnings},
50+
};
51+
if (teeName.empty())
52+
return logv2::LogTag::kNone;
53+
for (auto&& e : kTees)
54+
if (e.first == teeName)
55+
return e.second;
56+
MONGO_UNREACHABLE;
57+
}
58+
59+
} // namespace
60+
4261
/**
4362
* Appender for writing to a logv2 domain
4463
*/
@@ -51,6 +70,9 @@ class LogV2Appender : public Appender<Event> {
5170
explicit LogV2Appender(logv2::LogDomain* domain) : _domain(domain) {}
5271

5372
Status append(const Event& event) override {
73+
74+
auto logTagValue = findTeeTag(event.getTeeName());
75+
5476
logv2::detail::doLog(
5577

5678
// We need to cast from the v1 logging severity to the equivalent v2 severity
@@ -62,7 +84,7 @@ class LogV2Appender : public Appender<Event> {
6284
static_cast<std::underlying_type_t<LogComponent::Value>>(
6385
static_cast<LogComponent::Value>(event.getComponent())))),
6486
_domain,
65-
logv2::LogTag{}},
87+
logv2::LogTag{logTagValue}},
6688

6789
// stable id doesn't exist in logv1
6890
StringData{},

src/mongo/logger/message_event.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,17 @@ class MessageEventEphemeral {
6464
_contextName(contextName),
6565
_message(message) {}
6666

67+
void setTeeName(StringData tee) {
68+
_teeName = tee;
69+
}
6770
MessageEventEphemeral& setIsTruncatable(bool value) {
6871
_isTruncatable = value;
6972
return *this;
7073
}
7174

75+
StringData getTeeName() const {
76+
return _teeName;
77+
}
7278
Date_t getDate() const {
7379
return _date;
7480
}
@@ -95,6 +101,7 @@ class MessageEventEphemeral {
95101
StringData _contextName;
96102
StringData _message;
97103
bool _isTruncatable = true;
104+
StringData _teeName;
98105
};
99106

100107
} // namespace logger

src/mongo/logger/ramlog.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ class RamLog : public logger::Tee {
9393
*/
9494
void write(const std::string& str);
9595

96+
const std::string& getName() const {
97+
return _name;
98+
};
99+
96100
/**
97101
* Empties out the RamLog.
98102
*/

src/mongo/logv2/log_tag.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,18 @@ namespace mongo {
3636
namespace logv2 {
3737
class LogTag {
3838
public:
39-
enum Value { kNone = 0, kStartupWarnings = 1 << 0, kJavascript = 1 << 1 };
39+
enum Value {
40+
kNone = 0,
41+
42+
// replica set ramlog
43+
kRS = 1 << 0,
44+
45+
// startupWarnings ramlog
46+
kStartupWarnings = 1 << 1,
47+
48+
// representing the logv1 javascriptOutput domain
49+
kJavascript = 1 << 2,
50+
};
4051

4152
LogTag() : _value(kNone) {}
4253
/* implicit */ LogTag(Value value) {

src/mongo/util/log.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ void setPlainConsoleLogger() {
101101
std::make_unique<logger::MessageEventUnadornedEncoder>()));
102102
}
103103

104-
Tee* const warnings = RamLog::get("warnings"); // Things put here go in serverStatus
105104
Tee* const startupWarningsLog = RamLog::get("startupWarnings"); // intentionally leaked
106105

107106
} // namespace mongo

0 commit comments

Comments
 (0)