/* Copyright 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 .
*
* 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.
*/
#include "mongo/platform/basic.h"
#include "mongo/logger/log_component.h"
#include "mongo/base/init.h"
#include "mongo/util/assert_util.h"
namespace mongo {
namespace logger {
namespace {
// Component dotted names.
// Lazily evaluated in LogComponent::getDottedName().
std::string _dottedNames[LogComponent::kNumLogComponents + 1];
/**
* Returns StringData created from a string literal
*/
template
StringData createStringData(const char (&val)[N]) {
return StringData(val, StringData::LiteralTag());
}
//
// Fully initialize _dottedNames before we enter multithreaded execution.
//
MONGO_INITIALIZER_WITH_PREREQUISITES(SetupDottedNames, MONGO_NO_PREREQUISITES)
(InitializerContext* context) {
for (int i = 0; i <= int(LogComponent::kNumLogComponents); ++i) {
logger::LogComponent component = static_cast(i);
component.getDottedName();
}
return Status::OK();
}
} // namespace
// Children always come after parent component.
// This makes it unnecessary to compute children of each component
// when setting/clearing log severities in LogComponentSettings.
#define DECLARE_LOG_COMPONENT_PARENT(CHILD, PARENT) \
case (CHILD): \
do { \
static_assert(int(CHILD) > int(PARENT), "int(CHILD) > int(PARENT)"); \
return (PARENT); \
} while (0)
LogComponent LogComponent::parent() const {
switch (_value) {
case kDefault:
return kNumLogComponents;
DECLARE_LOG_COMPONENT_PARENT(kJournal, kStorage);
DECLARE_LOG_COMPONENT_PARENT(kASIO, kNetwork);
DECLARE_LOG_COMPONENT_PARENT(kBridge, kNetwork);
case kNumLogComponents:
return kNumLogComponents;
default:
return kDefault;
}
invariant(false);
}
StringData LogComponent::toStringData() const {
switch (_value) {
case kDefault:
return createStringData("default");
case kAccessControl:
return createStringData("accessControl");
case kCommand:
return createStringData("command");
case kControl:
return createStringData("control");
case kExecutor:
return createStringData("executor");
case kGeo:
return createStringData("geo");
case kIndex:
return createStringData("index");
case kNetwork:
return createStringData("network");
case kQuery:
return createStringData("query");
case kReplication:
return createStringData("replication");
case kSharding:
return createStringData("sharding");
case kStorage:
return createStringData("storage");
case kJournal:
return createStringData("journal");
case kWrite:
return createStringData("write");
case kFTDC:
return createStringData("ftdc");
case kASIO:
return createStringData("asio");
case kBridge:
return createStringData("bridge");
case kNumLogComponents:
return createStringData("total");
// No default. Compiler should complain if there's a log component that's not handled.
}
invariant(false);
}
std::string LogComponent::getShortName() const {
return toStringData().toString();
}
std::string LogComponent::getDottedName() const {
// Lazily evaluate dotted names in anonymous namespace.
if (_dottedNames[_value].empty()) {
switch (_value) {
case kDefault:
_dottedNames[_value] = getShortName();
break;
case kNumLogComponents:
_dottedNames[_value] = getShortName();
break;
default:
// Omit short name of 'default' component from dotted name.
if (parent() == kDefault) {
_dottedNames[_value] = getShortName();
} else {
_dottedNames[_value] = parent().getDottedName() + "." + getShortName();
}
break;
}
}
return _dottedNames[_value];
}
StringData LogComponent::getNameForLog() const {
switch (_value) {
case kDefault:
return createStringData("- ");
case kAccessControl:
return createStringData("ACCESS ");
case kCommand:
return createStringData("COMMAND ");
case kControl:
return createStringData("CONTROL ");
case kExecutor:
return createStringData("EXECUTOR");
case kGeo:
return createStringData("GEO ");
case kIndex:
return createStringData("INDEX ");
case kNetwork:
return createStringData("NETWORK ");
case kQuery:
return createStringData("QUERY ");
case kReplication:
return createStringData("REPL ");
case kSharding:
return createStringData("SHARDING");
case kStorage:
return createStringData("STORAGE ");
case kJournal:
return createStringData("JOURNAL ");
case kWrite:
return createStringData("WRITE ");
case kFTDC:
return createStringData("FTDC ");
case kASIO:
return createStringData("ASIO ");
case kBridge:
return createStringData("BRIDGE ");
case kNumLogComponents:
return createStringData("TOTAL ");
// No default. Compiler should complain if there's a log component that's not handled.
}
invariant(false);
}
std::ostream& operator<<(std::ostream& os, LogComponent component) {
return os << component.getNameForLog();
}
} // logger
} // mongo