Commit 031f579bd6cd4986dcd9bddd42771b2368842dd7
Committed by
Andrew Shvayka
1 parent
fc7b42c3
Email notifications for API state
Showing
5 changed files
with
46 additions
and
14 deletions
@@ -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 ${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 ${apiValueLabel}.<br> ${apiFeature} will be disabled for your account when limit will be reached. | 127 | + ThingsBoard has already ${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 |