ThingsBoard 任务处理失败通知模板化实战:${参数} 语法、大小写转换与多语言本地化
物联网后端数据可视化消息队列【免费下载链接】thingsboardAll-in-one IoT Platform - Device management, data collection, processing and visualization.项目地址https://gitcode.com/GitHub_Trending/th/thingsboard点击查看免费下载任务处理失败Task Processing Failure是 ThingsBoard 内置的通知类型之一当后台 Housekeeper 后台任务如遥测数据删除在多次重试后仍无法完成时触发。本文将围绕 ThingsBoard 通知模板的完整模板化与本地化语法展开逐项说明taskType、error、attempt等全部可用参数演示${...}包裹规则、upperCase/lowerCase/capitalize值修饰后缀以及translate多语言翻译后缀的用法并对照仓库源码揭示参数解析、错误堆栈截断与语言环境选取的底层实现帮助你编写可直接上线的失败告警通知模板。一、任务处理失败通知从哪里来触发链路速览在编写模板之前有必要先理解这类通知的产生时机。ThingsBoard 的HousekeeperService负责在后台异步执行清理类任务如删除遥测、删除告警、清理实体等。当任务执行抛出异常且当前重试次数attempt已达到配置的最大重试次数maxReprocessingAttempts时服务会构建并广播一个TaskProcessingFailureTrigger// application/src/main/java/org/thingsboard/server/service/housekeeper/HousekeeperService.java notificationRuleProcessor.process(TaskProcessingFailureTrigger.builder() .task(task) .error(error) .attempt(msg.getTask().getAttempt()) .build());随后TaskProcessingFailureTriggerProcessor将触发对象转换成通知信息供模板填充数据使用值得注意的一点是error异常堆栈在进入模板之前会被截断为最多 1024 个字符// application/src/main/java/org/thingsboard/server/service/notification/rule/trigger/TaskProcessingFailureTriggerProcessor.java return TaskProcessingFailureNotificationInfo.builder() .tenantId(task.getTenantId()) .entityId(task.getEntityId()) .taskType(task.getTaskType()) .taskDescription(task.getDescription()) .error(StringUtils.truncate(ExceptionUtils.getStackTrace(trigger.getError()), 1024)) .attempt(trigger.getAttempt()) .build();也就是说你在模板里看到的${error}是已截断的堆栈文本这是模板设计时就需要知道的约束。二、模板化与本地化概述任务处理失败通知的**主题subject、消息正文message和按钮文字button**均支持模板化templatization与本地化localization。模板化的核心语法是参数名用${...}包裹例如${entityType}可用参数集合由模板类型即通知类型决定——不同类型如告警、设备活动、任务失败等提供的参数不同本文聚焦任务处理失败类型模板值支持追加后缀来修改值的形态或触发翻译。TaskProcessingFailureNotificationInfo的getTemplateData()是这些参数的真正来源它把所有参数统一塞进一个MapString, String// common/data/src/main/java/org/thingsboard/server/common/data/notification/info/TaskProcessingFailureNotificationInfo.java return mapOf( tenantId, tenantId.toString(), entityType, entityId.getEntityType().getNormalName(), entityId, entityId.getId().toString(), taskType, taskType.getDescription(), taskDescription, taskDescription, error, error, attempt, String.valueOf(attempt) );三、可用模板参数完整清单任务处理失败通知模板支持以下参数对应TaskProcessingFailureNotificationInfo#getTemplateData与接收者上下文参数含义示例值说明taskType任务类型telemetry deletion来自 HousekeeperTaskType.java 枚举的 description 字段如attributes deletion、telemetry deletion、latest telemetry deletion、timeseries history deletion、events deletion、alarms deletion、entities cleanup等taskDescription任务描述telemetry deletion for device c4d93dc0-63a1-11ee-aa6d-f7cbc0a71325通常包含任务操作对象及其 ID便于快速定位error错误堆栈java.util.concurrent.ExecutionException: ...已被截断为最多 1024 字符tenantId租户 IDc4d93dc0-63a1-11ee-aa6d-f7cbc0a71325UUID 字符串entityType任务关联实体类型device实体的普通名称normal nameentityId任务关联实体 IDc4d93dc0-63a1-11ee-aa6d-f7cbc0a71325UUID 字符串attempt处理任务的重试次数5数字字符串即最终失败时的尝试次数recipientEmail接收者邮箱john.doeexample.com来自接收者用户资料recipientFirstName接收者名John来自接收者用户资料recipientLastName接收者姓Doe来自接收者用户资料前 7 个参数由失败任务本身产生后 3 个recipient*参数属于接收者上下文在渲染阶段由接收者资料动态注入见下文源码说明因此同一模板对不同接收者可产生不同文案。四、${...} 包裹语法与参数值修饰后缀1. 基本引用所有参数必须使用${参数名}形式包裹。例如Task type: ${taskType}2. 大小写与首字母修饰后缀除了直接引用还可以通过后缀修改参数值的形式后缀作用示例渲染结果upperCase全部转大写${entityType:upperCase}DEVICElowerCase全部转小写${entityType:lowerCase}devicecapitalize首字母大写${entityType:capitalize}Device这三个后缀的底层实现位于 TemplateUtils.java分别映射到String::toUpperCase、String::toLowerCase与StringUtils::capitalizeprivate static final MapString, UnaryOperatorString FUNCTIONS Map.of( upperCase, String::toUpperCase, lowerCase, String::toLowerCase, capitalize, StringUtils::capitalize );模板解析使用的正则\$\{(.?)(:[a-zA-Z])?}意味着后缀名只能由字母组成且可选。3. 无法解析参数时的行为从TemplateUtils的实现可以看到一个细节如果${...}中的键既不在上下文中、也没有可用的自定义函数模板会保留原样返回\${...}的转义形式而不是抛错。也就是说拼写错误的参数名会原样出现在通知文案中编写模板时务必核对参数名。五、translate 后缀与多语言本地化1. 基本用法使用translate后缀可以把一个翻译键translation key解析为当前语言的文本${some.translation.key:translate}2. 嵌套参数与翻译值翻译值本身也可以包含模板参数且会进行二次解析。文档给出的典型场景是自定义翻译键custom.notifications.greetings的值为Hello, ${recipientFirstName}!那么模板${custom.notifications.greetings:translate}会先通过翻译键取出Hello, ${recipientFirstName}!再对内部${recipientFirstName}做二次模板解析最终渲染为Hello, John!。这在 TemplateUtils.java 中由processTemplate(value, context, null)的递归调用实现。3. 语言环境从哪来翻译采用的语言locale取自接收者个人资料中的语言设置如果接收者没有设置语言则默认使用英语English。在 NotificationProcessingContext.java 中可以确认这一行为String locale recipient instanceof User user ? user.getLocale() : Locale.US.toString();而translate函数通过translationProvider按点号分隔的键路径如custom.notifications.greetings在翻译资源中查找文本functions Map.of(translate, key - translate(key, locale));翻译结果会在内存中按key - locale - value结构缓存避免重复加载。4. 本地化与接收者上下文的关系还有一个值得注意的渲染优化只有模板值中确实包含接收者相关变量如recipientFirstName或translate关键字时系统才会为每个接收者重新渲染模板否则使用同一份预渲染结果。这意味着模板设计者可以在不牺牲性能的前提下自由组合接收者个性化与翻译能力。六、完整实战示例示例一基础失败通知假设某设备c4d93dc0-63a1-11ee-aa6d-f7cbc0a71325的遥测删除任务最终失败模板Failed to process ${taskType} for ${entityType:lowerCase} ${entityId}将渲染为Failed to process telemetry deletion for device c4d93dc0-63a1-11ee-aa6d-f7cbc0a71325示例二包含错误信息与重试次数Task ${taskDescription} failed after ${attempt} attempts. Error: ${error}将渲染为Task telemetry deletion for device c4d93dc0-63a1-11ee-aa6d-f7cbc0a71325 failed after 5 attempts. Error: java.util.concurrent.ExecutionException: ...最多 1024 字符示例三接收者个性化Dear ${recipientFirstName} ${recipientLastName}, telemetry deletion failed for ${entityType} ${entityId}. Contact: ${recipientEmail}示例四多语言本地化若翻译资源中定义语言键值en_UScustom.notifications.taskFailureFailed to process ${taskType} for ${entityType:lowerCase}zh_CNcustom.notifications.taskFailure处理 ${entityType} ${entityId} 的 ${taskType} 任务失败模板写作${custom.notifications.taskFailure:translate}英语接收者将看到Failed to process telemetry deletion for device中文接收者在其资料中设置中文将看到处理 device c4d93dc0-63a1-11ee-aa6d-f7cbc0a71325 的 telemetry deletion 任务失败。语言自动按接收者资料切换未设置语言时默认英文。七、与系统默认模板的对照ThingsBoard 启动时会注册一组内置通知与默认规则任务处理失败通知的默认模板定义在 DefaultNotifications.javapublic static final DefaultNotification taskProcessingFailure DefaultNotification.builder() .name(Task processing failure notification) .type(NotificationType.TASK_PROCESSING_FAILURE) .subject(Failed to process ${taskType}) .text(Failed to process ${taskDescription} for tenant ${tenantId}: ${error}) .icon(warning).color(YELLOW_COLOR) .rule(DefaultRule.builder() .name(Task processing failure) .triggerConfig(TaskProcessingFailureNotificationRuleTriggerConfig.builder().build()) .description(Send notification to system admins when task processing fails) .build()) .build();可以看到默认实现即使用了${taskType}、${taskDescription}、${tenantId}、${error}四个参数——这与本文第三节的参数清单完全一致也印证了模板语法的实际效果。八、编写高质量失败通知模板的建议正文务必包含error与attempterror让你能直接定位失败根因注意 1024 字符截断attempt让你了解重试强度便于判断是偶发还是持续故障善用entityType修饰后缀${entityType:lowerCase}或${entityType:capitalize}可以生成自然流畅的英文文案避免DEVICE这类生硬形式区分任务参数与接收者参数taskType、error等来自失败任务本身与接收者无关recipientFirstName、recipientEmail等按人渲染适合做个性化问候本地化注意翻译值可嵌套translate的翻译值内部仍可引用${...}参数含其他接收者参数设计多语言资源时把变化的参数与固定的文案分离可大幅减少翻译条目数量核对参数名拼写不存在的参数不会报错而是原样输出${xxx}上线前建议用真实失败任务验证一次渲染结果留意失败窗口通知只在任务重试达到上限后触发见HousekeeperService中attempt maxReprocessingAttempts的判断分支因此该通知天然具备重试降噪能力无需在规则侧额外去重。九、相关源码与进一步阅读模板参数定义TaskProcessingFailureNotificationInfo.java触发处理与错误截断TaskProcessingFailureTriggerProcessor.java任务失败触发条件HousekeeperService.java模板解析与后缀实现TemplateUtils.java接收者上下文与翻译渲染NotificationProcessingContext.java任务类型描述枚举HousekeeperTaskType.java系统默认通知模板DefaultNotifications.java通知模型的前端定义notification.models.ts赞分享物联网后端数据可视化消息队列【免费下载链接】thingsboardAll-in-one IoT Platform - Device management, data collection, processing and visualization.项目地址https://gitcode.com/GitHub_Trending/th/thingsboard点击查看免费下载相关推荐ThingsBoard 通知模板化指南${} 参数、大小写修饰与多语言本地化ThingsBoard 通知模板化指南${} 参数、大小写修饰与多语言本地化 本指南讲解 ThingsBoard 物联网平台中通知模板的通用模板化templ物联网后端数据可视化消息队列ThingsBoard 实体数量上限通知模板化${...} 参数、大小写修饰符与多语言本地化实战ThingsBoard 实体数量上限通知模板化${...} 参数、大小写修饰符与多语言本地化实战 导读 本文围绕 ThingsBoard 通知中心Notif物联网后端数据可视化消息队列ThingsBoard Edge 连接通知模板化指南参数、大小写转换与国际化ThingsBoard Edge 连接通知模板化指南参数、大小写转换与国际化 导读 在 ThingsBoard 中当 Edge边缘节点与服务器建立或断开物联网后端数据可视化消息队列创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考