diff options
author | Billy Donahue <billy.donahue@mongodb.com> | 2020-06-25 17:30:24 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-06-30 20:17:23 +0000 |
commit | 8b2211d9a7b52a3ff951e9043966bbca3c555c30 (patch) | |
tree | 674eaebb98ffc617be500470bb7faa9a77be03b1 /src/mongo/logv2 | |
parent | 08e0e41a90051bd1fb6ac5fe3771fb7383c744af (diff) | |
download | mongo-8b2211d9a7b52a3ff951e9043966bbca3c555c30.tar.gz |
SERVER-47933 runtime attr unique check
Diffstat (limited to 'src/mongo/logv2')
-rw-r--r-- | src/mongo/logv2/attribute_storage.h | 9 | ||||
-rw-r--r-- | src/mongo/logv2/log_detail.cpp | 30 | ||||
-rw-r--r-- | src/mongo/logv2/logv2_test.cpp | 7 |
3 files changed, 46 insertions, 0 deletions
diff --git a/src/mongo/logv2/attribute_storage.h b/src/mongo/logv2/attribute_storage.h index 656302ba4de..141c10752a2 100644 --- a/src/mongo/logv2/attribute_storage.h +++ b/src/mongo/logv2/attribute_storage.h @@ -678,6 +678,8 @@ private: // Wrapper around internal pointer of AttributeStorage so it does not need any template parameters class TypeErasedAttributeStorage { public: + using const_iterator = const detail::NamedAttribute*; + TypeErasedAttributeStorage() : _size(0) {} template <typename... Args> @@ -695,6 +697,13 @@ public: return _size; } + const_iterator begin() const { + return _data; + } + const_iterator end() const { + return _data + _size; + } + // Applies a function to every stored named attribute in order they are captured template <typename Func> void apply(Func&& f) const { diff --git a/src/mongo/logv2/log_detail.cpp b/src/mongo/logv2/log_detail.cpp index 766c79488e4..e7863215590 100644 --- a/src/mongo/logv2/log_detail.cpp +++ b/src/mongo/logv2/log_detail.cpp @@ -31,12 +31,15 @@ #include "mongo/platform/basic.h" +#include <fmt/format.h> + #include "mongo/logv2/attributes.h" #include "mongo/logv2/log.h" #include "mongo/logv2/log_domain.h" #include "mongo/logv2/log_domain_internal.h" #include "mongo/logv2/log_options.h" #include "mongo/logv2/log_source.h" +#include "mongo/util/testing_proctor.h" namespace mongo::logv2::detail { @@ -99,12 +102,39 @@ private: std::deque<std::string> _storage; }; +static void checkUniqueAttrs(int32_t id, const TypeErasedAttributeStorage& attrs) { + if (attrs.size() <= 1) + return; + // O(N^2), but N is small and this avoids alloc, sort, and operator<. + auto first = attrs.begin(); + auto last = attrs.end(); + while (first != last) { + auto it = first; + ++first; + if (std::find_if(first, last, [&](auto&& a) { return a.name == it->name; }) == last) + continue; + StringData sep; + std::string msg; + for (auto&& a : attrs) { + msg.append(sep.rawData(), sep.size()) + .append("\"") + .append(a.name.rawData(), a.name.size()) + .append("\""); + sep = ","_sd; + } + uasserted(4793301, format(FMT_STRING("LOGV2 (id={}) attribute collision: [{}]"), id, msg)); + } +} + void doLogImpl(int32_t id, LogSeverity const& severity, LogOptions const& options, StringData message, TypeErasedAttributeStorage const& attrs) { dassert(options.component() != LogComponent::kNumLogComponents); + if (TestingProctor::instance().isEnabled()) + checkUniqueAttrs(id, attrs); + auto& source = options.domain().internal().source(); auto record = source.open_record(id, severity, diff --git a/src/mongo/logv2/logv2_test.cpp b/src/mongo/logv2/logv2_test.cpp index e5c702a1f7c..f863c7db555 100644 --- a/src/mongo/logv2/logv2_test.cpp +++ b/src/mongo/logv2/logv2_test.cpp @@ -1318,6 +1318,13 @@ TEST_F(LogV2ContainerTest, StringMapUint32) { }); } +TEST_F(LogV2Test, AttrNameCollision) { + ASSERT_THROWS_CODE( + LOGV2(4793300, "Collision {k1}", "Collision", "k1"_attr = "v1", "k1"_attr = "v2"), + AssertionException, + 4793301); +} + TEST_F(LogV2Test, Unicode) { auto lines = makeLineCapture(JSONFormatter()); |