Skip to content

Commit e83c0f3

Browse files
committed
add(combinator): displayExpression aggregation handling
1 parent d4c4b20 commit e83c0f3

File tree

1 file changed

+86
-28
lines changed

1 file changed

+86
-28
lines changed

src/combinator.cpp

Lines changed: 86 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <fmt/format.h>
2727

2828
#include <numeric>
29+
#include <stdexcept>
2930
#include <unordered_set>
3031

3132
using Log = metricq::logger::nitro::Log;
@@ -50,45 +51,102 @@ Combinator::~Combinator()
5051
{
5152
}
5253

53-
std::string displayExpression(const nlohmann::json& expression) {
54+
std::string handleBasicExpression(const nlohmann::json& expression)
55+
{
56+
if (expression.is_number())
57+
{
58+
auto value = expression.get<double>();
59+
return (value == static_cast<int>(value)) ? std::to_string(static_cast<int>(value)) :
60+
std::to_string(value);
61+
}
62+
63+
if (expression.is_string())
64+
{
65+
return expression.get<std::string>();
66+
}
67+
68+
throw std::runtime_error("Expression is not a basic type (number or string)!");
69+
}
70+
71+
std::string handleOperatorExpression(const std::string& operation, const std::string& leftStr,
72+
const std::string& rightStr)
73+
{
5474
static const std::unordered_set<std::string> validOperators = { "+", "-", "*", "/" };
5575

56-
// Check if the expression is a number and return it as a string
57-
if (expression.is_number()) {
58-
double value = expression.get<double>();
59-
return (value == static_cast<int>(value)) ? std::to_string(static_cast<int>(value)) : std::to_string(value);
76+
if (validOperators.find(operation) == validOperators.end())
77+
{
78+
throw std::runtime_error("Invalid operator: " + operation);
6079
}
6180

62-
if (expression.is_object() && expression.contains("operation")) {
63-
std::string operation = expression.value("operation", "");
81+
return operation + (leftStr.empty() ? "" : " " + leftStr) +
82+
(rightStr.empty() ? "" : " " + rightStr);
83+
}
6484

65-
// Validate if the operation is supported
66-
if (validOperators.find(operation) == validOperators.end()) {
67-
return operation;
68-
}
85+
std::string handleAggregateExpression(const std::string& operation,
86+
const std::vector<std::string>& inputs)
87+
{
88+
static const std::unordered_set<std::string> validAggregates = { "sum", "min", "max" };
6989

70-
// Helper lambda to process operands
71-
auto processOperand = [&](const std::string& key) -> std::string {
72-
if (expression.contains(key)) {
73-
const auto& operand = expression[key];
74-
if (operand.is_string()) return operand.get<std::string>();
75-
if (operand.is_number()) return std::to_string(operand.get<int>());
76-
return displayExpression(operand);
77-
}
78-
return "";
79-
};
90+
if (validAggregates.find(operation) == validAggregates.end())
91+
{
92+
throw std::runtime_error("Invalid aggregate operation: " + operation);
93+
}
8094

81-
std::string leftStr = processOperand("left");
82-
std::string rightStr = processOperand("right");
83-
return operation + (leftStr.empty() ? "" : " " + leftStr) + (rightStr.empty() ? "" : " " + rightStr);
95+
if (inputs.empty())
96+
{
97+
throw std::logic_error("Aggregate operation missing inputs!");
8498
}
8599

86-
// If the expression is a string, return it directly
87-
if (expression.is_string()) {
88-
return expression.get<std::string>();
100+
auto input = std::accumulate(std::next(inputs.begin()), inputs.end(), inputs[0],
101+
[](std::string a, const std::string& b) { return a + ", " + b; });
102+
103+
return operation + ": [" + input + "]";
104+
}
105+
106+
std::string displayExpression(const nlohmann::json& expression)
107+
{
108+
if (expression.is_number() || expression.is_string())
109+
{
110+
return handleBasicExpression(expression);
111+
}
112+
113+
if (!expression.is_object() || !expression.contains("operation"))
114+
{
115+
throw std::runtime_error("Unknown expression format!");
116+
}
117+
118+
std::string operation = expression.value("operation", "");
119+
120+
if (operation == "throttle")
121+
{
122+
return operation;
123+
}
124+
125+
if (expression.contains("left") || expression.contains("right"))
126+
{
127+
std::string leftStr =
128+
expression.contains("left") ? displayExpression(expression["left"]) : "";
129+
std::string rightStr =
130+
expression.contains("right") ? displayExpression(expression["right"]) : "";
131+
return handleOperatorExpression(operation, leftStr, rightStr);
132+
}
133+
134+
if (expression.contains("inputs"))
135+
{
136+
if (!expression["inputs"].is_array())
137+
{
138+
throw std::logic_error("Inputs must be an array!");
139+
}
140+
141+
std::vector<std::string> inputStrings;
142+
for (const auto& input : expression["inputs"])
143+
{
144+
inputStrings.push_back(displayExpression(input));
145+
}
146+
return handleAggregateExpression(operation, inputStrings);
89147
}
90148

91-
return "Unknown expression format";
149+
throw std::runtime_error("Unsupported operation type: " + operation);
92150
}
93151

94152
void Combinator::on_transformer_config(const metricq::json& config)

0 commit comments

Comments
 (0)