Commit 031f579bd6cd4986dcd9bddd42771b2368842dd7

Authored by Andrii Shvaika
Committed by Andrew Shvayka
1 parent fc7b42c3

Email notifications for API state

... ... @@ -20,6 +20,7 @@ import freemarker.template.Configuration;
20 20 import freemarker.template.Template;
21 21 import lombok.extern.slf4j.Slf4j;
22 22 import org.apache.commons.lang3.StringUtils;
  23 +import org.jetbrains.annotations.NotNull;
23 24 import org.springframework.beans.factory.annotation.Autowired;
24 25 import org.springframework.context.MessageSource;
25 26 import org.springframework.core.NestedRuntimeException;
... ... @@ -55,6 +56,8 @@ public class DefaultMailService implements MailService {
55 56 public static final String MAIL_PROP = "mail.";
56 57 public static final String TARGET_EMAIL = "targetEmail";
57 58 public static final String UTF_8 = "UTF-8";
  59 + public static final int _10K = 10000;
  60 + public static final int _1M = 1000000;
58 61 @Autowired
59 62 private MessageSource messages;
60 63
... ... @@ -266,8 +269,7 @@ public class DefaultMailService implements MailService {
266 269 message = mergeTemplateIntoString("state.enabled.ftl", model);
267 270 break;
268 271 case WARNING:
269   - model.put("apiLimitValueLabel", toDisabledValueLabel(msg.getKey(), msg.getThreshold()));
270   - model.put("apiValueLabel", toDisabledValueLabel(apiFeature) + " " + toDisabledValueLabel(msg.getKey(), msg.getValue()));
  272 + model.put("apiValueLabel", toDisabledValueLabel(apiFeature) + " " + toWarningValueLabel(msg.getKey(), msg.getValue(), msg.getThreshold()));
271 273 message = mergeTemplateIntoString("state.warning.ftl", model);
272 274 break;
273 275 case DISABLED:
... ... @@ -285,8 +287,9 @@ public class DefaultMailService implements MailService {
285 287 case TRANSPORT:
286 288 return "receive";
287 289 case JS:
288   - case RE:
289 290 return "invoke";
  291 + case RE:
  292 + return "process";
290 293 default:
291 294 throw new RuntimeException("Not implemented!");
292 295 }
... ... @@ -299,8 +302,27 @@ public class DefaultMailService implements MailService {
299 302 case TRANSPORT:
300 303 return "received";
301 304 case JS:
302   - case RE:
303 305 return "invoked";
  306 + case RE:
  307 + return "processed";
  308 + default:
  309 + throw new RuntimeException("Not implemented!");
  310 + }
  311 + }
  312 +
  313 + private String toWarningValueLabel(ApiUsageRecordKey key, long value, long threshold) {
  314 + String valueInM = getValueAsString(value);
  315 + String thresholdInM = getValueAsString(threshold);
  316 + switch (key) {
  317 + case STORAGE_DP_COUNT:
  318 + case TRANSPORT_DP_COUNT:
  319 + return valueInM + " out of " + thresholdInM + " allowed data points";
  320 + case TRANSPORT_MSG_COUNT:
  321 + return valueInM + " out of " + thresholdInM + " allowed messages";
  322 + case JS_EXEC_COUNT:
  323 + return valueInM + " out of " + thresholdInM + " allowed JavaScript functions";
  324 + case RE_EXEC_COUNT:
  325 + return valueInM + " out of " + thresholdInM + " allowed Rule Engine messages";
304 326 default:
305 327 throw new RuntimeException("Not implemented!");
306 328 }
... ... @@ -310,18 +332,29 @@ public class DefaultMailService implements MailService {
310 332 switch (key) {
311 333 case STORAGE_DP_COUNT:
312 334 case TRANSPORT_DP_COUNT:
313   - return (value / 1000000) + "M data points";
  335 + return getValueAsString(value) + " data points";
314 336 case TRANSPORT_MSG_COUNT:
315   - return (value / 1000000) + "M messages";
  337 + return getValueAsString(value) + " messages";
316 338 case JS_EXEC_COUNT:
317   - return (value / 1000000) + "M JavaScript functions";
  339 + return "JavaScript functions " + getValueAsString(value) + " times";
318 340 case RE_EXEC_COUNT:
319   - return (value / 1000000) + "M Rule Engine nodes";
  341 + return getValueAsString(value) + " Rule Engine messages";
320 342 default:
321 343 throw new RuntimeException("Not implemented!");
322 344 }
323 345 }
324 346
  347 + @NotNull
  348 + private String getValueAsString(long value) {
  349 + if (value > _1M && value % _1M < _10K) {
  350 + return value / _1M + "M";
  351 + } else if (value > _10K) {
  352 + return String.format("%.2fM", ((double) value) / 1000000);
  353 + } else {
  354 + return value + "";
  355 + }
  356 + }
  357 +
325 358 private void sendMail(JavaMailSenderImpl mailSender,
326 359 String mailFrom, String email,
327 360 String subject, String message) throws ThingsboardException {
... ...
... ... @@ -123,8 +123,7 @@
123 123 <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
124 124 <td class="content-block"
125 125 style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0px; padding: 0px 0px 20px; height: 40px;"
126   - valign="top">We have disabled the ${apiFeature} for your account because ThingsBoard has already&nbsp; ${apiLimitValueLabel}
127   - .
  126 + valign="top">We have disabled the ${apiFeature} for your account because ThingsBoard has already ${apiLimitValueLabel}.
128 127 </td>
129 128 </tr>
130 129 <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
... ...
... ... @@ -123,7 +123,7 @@
123 123 <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
124 124 <td class="content-block"
125 125 style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0px; padding: 0px 0px 20px; height: 40px;"
126   - valign="top">We have enabled the ${apiFeature} for your account and ThingsBoard already able to ${apiLabel} messages.
  126 + valign="top">We have enabled the ${apiFeature} for your account and ThingsBoard is already able to ${apiLabel} messages.
127 127 </td>
128 128 </tr>
129 129 <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
... ...
... ... @@ -117,14 +117,14 @@
117 117 <td class="content-block"
118 118 style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; color: #348eda; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0px; padding: 0px 0px 20px; height: 84px;"
119 119 valign="top">
120   - <h2>Your ThingsBoard account feature may be disabled</h2>
  120 + <h2>Your ThingsBoard account feature may be disabled soon</h2>
121 121 </td>
122 122 </tr>
123 123 <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
124 124 <td class="content-block"
125 125 style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 14px; vertical-align: top; margin: 0px; padding: 0px 0px 20px; height: 40px;"
126 126 valign="top">
127   - Your ${apiFeature} limit (${apiLimitValueLabel}) is almost exhausted. <br>ThingsBoard has already&nbsp;${apiValueLabel}.<br> ${apiFeature} will be disabled for your account when limit will be reached.
  127 + ThingsBoard has already&nbsp;${apiValueLabel}.<br> ${apiFeature} will be disabled for your account once the limit will be reached.
128 128 </td>
129 129 </tr>
130 130 <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
... ...
... ... @@ -20,7 +20,7 @@ import lombok.Getter;
20 20 public enum ApiFeature {
21 21 TRANSPORT("transportApiState", "Device API"),
22 22 DB("dbApiState", "Telemetry persistence"),
23   - RE("ruleEngineApiState", "Rule engine execution"),
  23 + RE("ruleEngineApiState", "Rule Engine execution"),
24 24 JS("jsExecutionApiState", "JavaScript functions execution");
25 25
26 26 @Getter
... ...