Skip to content

Commit

Permalink
feat(json): add filter option to json formatter
Browse files Browse the repository at this point in the history
Json formatter now can optionally filter duplicate
attributes in a reverse order.

This option is disabled by default, but can be
enabled by specifying a `filter: true` in the
config.
  • Loading branch information
3Hren committed Oct 20, 2015
1 parent 076abc6 commit b8518da
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 4 deletions.
34 changes: 30 additions & 4 deletions src/blackhole/formatter/json.hpp
Expand Up @@ -3,6 +3,7 @@
#include <list>
#include <string>
#include <vector>
#include <unordered_set>
#include <unordered_map>

#include <rapidjson/document.h>
Expand Down Expand Up @@ -172,10 +173,29 @@ class json_t : public base_t {
root.SetObject();

json_visitor_t visitor(&root, config, mapper);
for (auto it = record.attributes().begin(); it != record.attributes().end(); ++it) {
const std::string& name = it->first;
const attribute_t& attribute = it->second;
aux::apply_visitor(visitor, name, attribute.value);

const auto& attributes = record.attributes().partial();

if (config.filter) {
std::unordered_set<std::string> duplicates;

for (auto it = attributes.rbegin(); it != attributes.rend(); ++it) {
const std::string& name = it->first;
const attribute_t& attribute = it->second;

if (!duplicates.insert(name).second) {
// Filter duplicates.
continue;
}

aux::apply_visitor(visitor, name, attribute.value);
}
} else {
for (auto it = attributes.begin(); it != attributes.end(); ++it) {
const std::string& name = it->first;
const attribute_t& attribute = it->second;
aux::apply_visitor(visitor, name, attribute.value);
}
}

rapidjson::GenericStringBuffer<rapidjson::UTF8<>> buffer;
Expand All @@ -200,6 +220,12 @@ struct factory_traits<formatter::json_t> {
static
void
map_config(const aux::extractor<formatter_type>& ex, config_type& config) {
try {
ex["filter"].to(config.filter);
} catch (const error_t&) {
config.filter = false;
}

ex["newline"].to(config.newline);

auto mapping = ex["mapping"].get<dynamic_t::object_t>();
Expand Down
2 changes: 2 additions & 0 deletions src/blackhole/formatter/json/config.hpp
Expand Up @@ -26,11 +26,13 @@ struct routing_t {
} // namespace map

struct config_t {
bool filter;
bool newline;
map::mapping_t naming;
map::routing_t routing;

config_t() :
filter(false),
newline(false)
{}
};
Expand Down
23 changes: 23 additions & 0 deletions src/tests/test_JsonFormatter.cpp
Expand Up @@ -240,3 +240,26 @@ TEST(json_t, AttributeMappingIsDeterminedByItsBaseNames) {
ASSERT_TRUE(doc["@secret"].IsString());
EXPECT_STREQ("(42)", doc["@secret"].GetString());
}

TEST(json_t, AllowDuplicateAttributes) {
record_t record;
record.insert(keyword::message() = "le message1");
record.insert(keyword::message() = "le message2");

formatter::json_t fmt;
std::string expected = "{\"message\":\"le message1\",\"message\":\"le message2\"}";
EXPECT_EQ(expected, fmt.format(record));
}

TEST(json_t, DisallowDuplicateAttributesIfNeeded) {
record_t record;
record.insert(keyword::message() = "le message1");
record.insert(keyword::message() = "le message2");

formatter::json::config_t config;
config.filter = true;

formatter::json_t fmt(config);
std::string expected = "{\"message\":\"le message2\"}";
EXPECT_EQ(expected, fmt.format(record));
}

0 comments on commit b8518da

Please sign in to comment.