-
Notifications
You must be signed in to change notification settings - Fork 0
FOGL-9963 Add Alerts as a source for notifications #104
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 15 commits
d42fb17
986a170
92cf16f
2f039fb
3ffa5a6
56dadba
75f0ace
f1b6e05
f984d05
70306ac
a1b5e15
833f636
7889c20
c2b192d
e95d88c
ac4e8a9
0a495ba
682ff5a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -45,6 +45,13 @@ static const char *default_config = QUOTE({ | |
"default" : "", | ||
"displayName" : "Asset Code", | ||
"order" : "3" | ||
}, | ||
"alerts" : { | ||
"description" : "Deliver alert data to the notificaiton delivery mechanism", | ||
"type" : "boolean", | ||
"default" : "false", | ||
"displayName" : "Alerts", | ||
"order" : "4" | ||
} | ||
}); | ||
|
||
|
@@ -147,6 +154,12 @@ string DataAvailabilityRule::triggers() | |
ret += "{ \"audit\" : \"" + audit + "\" }"; | ||
comma = ","; | ||
} | ||
if (m_alert) | ||
{ | ||
ret += comma; | ||
ret += "{ \"alert\" : \"alert\" }"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why the hardcoded string value "alert", same as key? In future, We better use |
||
comma = ","; | ||
} | ||
ret += " ] }"; | ||
return ret; | ||
} | ||
|
@@ -339,5 +352,14 @@ void DataAvailabilityRule::configure(const ConfigCategory &config) | |
DatapointValue value (m_assetCodeList[i]); | ||
handle->addTrigger(m_assetCodeList[i], new RuleTrigger(m_assetCodeList[i], new Datapoint(m_assetCodeList[i], value))); | ||
} | ||
|
||
string alerts = config.getValue("alerts"); | ||
m_alert = alerts[0] == 't' ? true : false; | ||
if (m_alert) | ||
{ | ||
DatapointValue dpv("alert"); | ||
handle->addTrigger("alert", new RuleTrigger("alert", new Datapoint("alert", dpv))); | ||
} | ||
|
||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,8 +9,10 @@ | |
*/ | ||
|
||
#include <delivery_plugin.h> | ||
#include <rapidjson/document.h> | ||
|
||
using namespace std; | ||
using namespace rapidjson; | ||
|
||
|
||
// DeliveryPlugin constructor | ||
|
@@ -115,7 +117,7 @@ bool DeliveryPlugin::deliver(const std::string& deliveryName, | |
deliveryName, | ||
notificationName, | ||
triggerReason, | ||
message); | ||
expandMacros(message, triggerReason)); | ||
} | ||
unsigned int duration = time(0) - start; | ||
if (duration > 5) | ||
|
@@ -188,3 +190,129 @@ void DeliveryPlugin::registerService(void *func, void *data) | |
(*pluginRegisterService)(m_instance, func, data); | ||
} | ||
} | ||
|
||
|
||
/** | ||
* Create the information about the macros to substitute in the given string | ||
* | ||
* @param str The string we are substituting | ||
* @param macros Vector of macros to build up | ||
*/ | ||
void DeliveryPlugin::collectMacroInfo(const string& str, vector<Macro>& macros) | ||
{ | ||
string::size_type start = str.find('$'); | ||
string::size_type end = str.find('$', start + 1); | ||
|
||
while (start != string::npos && end != string::npos) | ||
{ | ||
string::size_type bar = str.find('|', start + 1); | ||
if (bar != string::npos && bar < end && bar > start + 1) | ||
{ | ||
string def = str.substr(bar + 1, end - bar - 1); | ||
macros.emplace_back(Macro(str.substr(start + 1, bar - start - 1), start, def)); | ||
} | ||
else if (end > start + 1) | ||
{ | ||
macros.emplace_back(Macro(str.substr(start + 1, end - start - 1), start)); | ||
} | ||
start = str.find('$', end + 1); | ||
end = str.find('$', start + 1); | ||
} | ||
} | ||
|
||
/** | ||
* Substitute values from the reason into the string. | ||
* Macros are of the form $key$ or | ||
* $key|default$. Where key is one of the keys found in | ||
* the notification data of the reason document. Keys | ||
* are typical datapoint names that triggered the alert | ||
* for readings, statis values for statistics data and | ||
* messages for alert data. | ||
* | ||
* @param message The string to substitute into | ||
* @param reason The notification reason from which to pull data | ||
* @return string The substituted string | ||
*/ | ||
string DeliveryPlugin::expandMacros(const string& message, const string& reason) | ||
{ | ||
string rval = message; | ||
vector<Macro> macros; | ||
Logger::getLogger()->debug("Expand macros in messge %s with reason %s", | ||
|
||
message.c_str(), reason.c_str()); | ||
collectMacroInfo(rval, macros); | ||
if (macros.size()) | ||
{ | ||
Document doc; | ||
doc.Parse(reason.c_str()); | ||
if (doc.HasParseError()) | ||
{ | ||
// Failed to parse the reason, ignore macros | ||
Logger::getLogger()->warn("Unable to parse reason document, macro substitutios withinthe notification will be ignored. The reason document is: %s", reason.c_str()); | ||
|
||
return rval; | ||
} | ||
if (!doc.HasMember("data")) | ||
{ | ||
Logger::getLogger()->warn("Unable to perform macro substitution in the notifcation alert. No data element was found in reason document %s", reason.c_str()); | ||
return rval; | ||
} | ||
Value& data = doc["data"]; | ||
Value::ConstMemberIterator itr = data.MemberBegin(); | ||
if (itr == data.MemberEnd()) | ||
{ | ||
Logger::getLogger()->warn("Unable to perform macro substitution in the notifcation alert. No data element has no children, reason document %s", reason.c_str()); | ||
|
||
return rval; | ||
} | ||
const Value& v = itr->value; | ||
string assetName = itr->name.GetString(); | ||
|
||
|
||
// Replace Macros by datapoint value | ||
for (auto it = macros.rbegin(); it != macros.rend(); ++it) | ||
{ | ||
if (v.HasMember(it->name.c_str())) | ||
{ | ||
string val; | ||
if (v[it->name.c_str()].IsString()) | ||
{ | ||
val = v[it->name.c_str()].GetString(); | ||
} | ||
else if (v[it->name.c_str()].IsInt64()) | ||
{ | ||
val = to_string(v[it->name.c_str()].GetInt64()); | ||
} | ||
else if (v[it->name.c_str()].IsDouble()) | ||
{ | ||
val = to_string(v[it->name.c_str()].GetDouble()); | ||
// Trim trailing 0's | ||
size_t len = val.length(); | ||
while (len > 0 && val[len-1] == '0') | ||
{ | ||
len--; | ||
} | ||
if (len > 0) | ||
{ | ||
val = val.substr(0, len); | ||
} | ||
|
||
} | ||
else | ||
{ | ||
Logger::getLogger()->warn("The datapoint %s cannot be used as a macro substitution as it is not a string or numeric value",it->name.c_str()); | ||
continue; | ||
} | ||
rval.replace(it->start, it->name.length()+2 | ||
+ (it->def.empty() ? 0 : it->def.length() + 1), | ||
val ); | ||
} | ||
else if (!it->def.empty()) | ||
{ | ||
rval.replace(it->start, it->name.length() + it->def.length() + 3, it->def); | ||
} | ||
else | ||
{ | ||
rval.replace(it->start, it->name.length()+2, ""); | ||
} | ||
} | ||
} | ||
return rval; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
notificaiton typo