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,6 +20,7 @@ import freemarker.template.Configuration;
20 import freemarker.template.Template; 20 import freemarker.template.Template;
21 import lombok.extern.slf4j.Slf4j; 21 import lombok.extern.slf4j.Slf4j;
22 import org.apache.commons.lang3.StringUtils; 22 import org.apache.commons.lang3.StringUtils;
  23 +import org.jetbrains.annotations.NotNull;
23 import org.springframework.beans.factory.annotation.Autowired; 24 import org.springframework.beans.factory.annotation.Autowired;
24 import org.springframework.context.MessageSource; 25 import org.springframework.context.MessageSource;
25 import org.springframework.core.NestedRuntimeException; 26 import org.springframework.core.NestedRuntimeException;
@@ -55,6 +56,8 @@ public class DefaultMailService implements MailService { @@ -55,6 +56,8 @@ public class DefaultMailService implements MailService {
55 public static final String MAIL_PROP = "mail."; 56 public static final String MAIL_PROP = "mail.";
56 public static final String TARGET_EMAIL = "targetEmail"; 57 public static final String TARGET_EMAIL = "targetEmail";
57 public static final String UTF_8 = "UTF-8"; 58 public static final String UTF_8 = "UTF-8";
  59 + public static final int _10K = 10000;
  60 + public static final int _1M = 1000000;
58 @Autowired 61 @Autowired
59 private MessageSource messages; 62 private MessageSource messages;
60 63
@@ -266,8 +269,7 @@ public class DefaultMailService implements MailService { @@ -266,8 +269,7 @@ public class DefaultMailService implements MailService {
266 message = mergeTemplateIntoString("state.enabled.ftl", model); 269 message = mergeTemplateIntoString("state.enabled.ftl", model);
267 break; 270 break;
268 case WARNING: 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 message = mergeTemplateIntoString("state.warning.ftl", model); 273 message = mergeTemplateIntoString("state.warning.ftl", model);
272 break; 274 break;
273 case DISABLED: 275 case DISABLED:
@@ -285,8 +287,9 @@ public class DefaultMailService implements MailService { @@ -285,8 +287,9 @@ public class DefaultMailService implements MailService {
285 case TRANSPORT: 287 case TRANSPORT:
286 return "receive"; 288 return "receive";
287 case JS: 289 case JS:
288 - case RE:  
289 return "invoke"; 290 return "invoke";
  291 + case RE:
  292 + return "process";
290 default: 293 default:
291 throw new RuntimeException("Not implemented!"); 294 throw new RuntimeException("Not implemented!");
292 } 295 }
@@ -299,8 +302,27 @@ public class DefaultMailService implements MailService { @@ -299,8 +302,27 @@ public class DefaultMailService implements MailService {
299 case TRANSPORT: 302 case TRANSPORT:
300 return "received"; 303 return "received";
301 case JS: 304 case JS:
302 - case RE:  
303 return "invoked"; 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 default: 326 default:
305 throw new RuntimeException("Not implemented!"); 327 throw new RuntimeException("Not implemented!");
306 } 328 }
@@ -310,18 +332,29 @@ public class DefaultMailService implements MailService { @@ -310,18 +332,29 @@ public class DefaultMailService implements MailService {
310 switch (key) { 332 switch (key) {
311 case STORAGE_DP_COUNT: 333 case STORAGE_DP_COUNT:
312 case TRANSPORT_DP_COUNT: 334 case TRANSPORT_DP_COUNT:
313 - return (value / 1000000) + "M data points"; 335 + return getValueAsString(value) + " data points";
314 case TRANSPORT_MSG_COUNT: 336 case TRANSPORT_MSG_COUNT:
315 - return (value / 1000000) + "M messages"; 337 + return getValueAsString(value) + " messages";
316 case JS_EXEC_COUNT: 338 case JS_EXEC_COUNT:
317 - return (value / 1000000) + "M JavaScript functions"; 339 + return "JavaScript functions " + getValueAsString(value) + " times";
318 case RE_EXEC_COUNT: 340 case RE_EXEC_COUNT:
319 - return (value / 1000000) + "M Rule Engine nodes"; 341 + return getValueAsString(value) + " Rule Engine messages";
320 default: 342 default:
321 throw new RuntimeException("Not implemented!"); 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 private void sendMail(JavaMailSenderImpl mailSender, 358 private void sendMail(JavaMailSenderImpl mailSender,
326 String mailFrom, String email, 359 String mailFrom, String email,
327 String subject, String message) throws ThingsboardException { 360 String subject, String message) throws ThingsboardException {
@@ -123,8 +123,7 @@ @@ -123,8 +123,7 @@
123 <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> 123 <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
124 <td class="content-block" 124 <td class="content-block"
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;" 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 </td> 127 </td>
129 </tr> 128 </tr>
130 <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> 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,7 +123,7 @@
123 <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> 123 <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
124 <td class="content-block" 124 <td class="content-block"
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;" 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 </td> 127 </td>
128 </tr> 128 </tr>
129 <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> 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,14 +117,14 @@
117 <td class="content-block" 117 <td class="content-block"
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;" 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 valign="top"> 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 </td> 121 </td>
122 </tr> 122 </tr>
123 <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> 123 <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;">
124 <td class="content-block" 124 <td class="content-block"
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;" 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"> 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 </td> 128 </td>
129 </tr> 129 </tr>
130 <tr style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; margin: 0;"> 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,7 +20,7 @@ import lombok.Getter;
20 public enum ApiFeature { 20 public enum ApiFeature {
21 TRANSPORT("transportApiState", "Device API"), 21 TRANSPORT("transportApiState", "Device API"),
22 DB("dbApiState", "Telemetry persistence"), 22 DB("dbApiState", "Telemetry persistence"),
23 - RE("ruleEngineApiState", "Rule engine execution"), 23 + RE("ruleEngineApiState", "Rule Engine execution"),
24 JS("jsExecutionApiState", "JavaScript functions execution"); 24 JS("jsExecutionApiState", "JavaScript functions execution");
25 25
26 @Getter 26 @Getter