Commit 08ab9752fccb95fa8931e3247c252c8dc9d09f02

Authored by Andrii Shvaika
1 parent d2919ba3

Better logging of Rule Engine errors

@@ -163,7 +163,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh @@ -163,7 +163,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
163 String dispatcherName = tenantId.getId().equals(EntityId.NULL_UUID) ? 163 String dispatcherName = tenantId.getId().equals(EntityId.NULL_UUID) ?
164 DefaultActorService.SYSTEM_RULE_DISPATCHER_NAME : DefaultActorService.TENANT_RULE_DISPATCHER_NAME; 164 DefaultActorService.SYSTEM_RULE_DISPATCHER_NAME : DefaultActorService.TENANT_RULE_DISPATCHER_NAME;
165 return context.actorOf( 165 return context.actorOf(
166 - Props.create(new RuleNodeActor.ActorCreator(systemContext, tenantId, entityId, ruleNode.getId())) 166 + Props.create(new RuleNodeActor.ActorCreator(systemContext, tenantId, entityId, ruleNode.getName(), ruleNode.getId()))
167 .withDispatcher(dispatcherName), ruleNode.getId().toString()); 167 .withDispatcher(dispatcherName), ruleNode.getId().toString());
168 } 168 }
169 169
@@ -200,7 +200,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh @@ -200,7 +200,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
200 log.trace("[{}][{}] Processing message [{}]: {}", entityId, firstId, msg.getId(), msg); 200 log.trace("[{}][{}] Processing message [{}]: {}", entityId, firstId, msg.getId(), msg);
201 if (envelope.getRelationTypes() == null || envelope.getRelationTypes().isEmpty()) { 201 if (envelope.getRelationTypes() == null || envelope.getRelationTypes().isEmpty()) {
202 try { 202 try {
203 - checkActive(); 203 + checkActive(envelope.getTbMsg());
204 RuleNodeId targetId = msg.getRuleNodeId(); 204 RuleNodeId targetId = msg.getRuleNodeId();
205 RuleNodeCtx targetCtx; 205 RuleNodeCtx targetCtx;
206 if (targetId == null) { 206 if (targetId == null) {
@@ -216,6 +216,8 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh @@ -216,6 +216,8 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
216 log.trace("[{}][{}] Rule node does not exist. Probably old message", entityId, targetId); 216 log.trace("[{}][{}] Rule node does not exist. Probably old message", entityId, targetId);
217 msg.getCallback().onSuccess(); 217 msg.getCallback().onSuccess();
218 } 218 }
  219 + } catch (RuleNodeException rne) {
  220 + envelope.getTbMsg().getCallback().onFailure(rne);
219 } catch (Exception e) { 221 } catch (Exception e) {
220 envelope.getTbMsg().getCallback().onFailure(new RuleEngineException(e.getMessage())); 222 envelope.getTbMsg().getCallback().onFailure(new RuleEngineException(e.getMessage()));
221 } 223 }
@@ -225,11 +227,15 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh @@ -225,11 +227,15 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
225 } 227 }
226 228
227 void onRuleChainToRuleChainMsg(RuleChainToRuleChainMsg envelope) { 229 void onRuleChainToRuleChainMsg(RuleChainToRuleChainMsg envelope) {
228 - checkActive();  
229 - if (firstNode != null) {  
230 - pushMsgToNode(firstNode, envelope.getMsg(), envelope.getFromRelationType());  
231 - } else {  
232 - envelope.getMsg().getCallback().onSuccess(); 230 + try {
  231 + checkActive(envelope.getMsg());
  232 + if (firstNode != null) {
  233 + pushMsgToNode(firstNode, envelope.getMsg(), envelope.getFromRelationType());
  234 + } else {
  235 + envelope.getMsg().getCallback().onSuccess();
  236 + }
  237 + } catch (RuleNodeException e) {
  238 + log.debug("Rule Chain is not active. Current state [{}] for processor [{}][{}] tenant [{}]", state, entityId.getEntityType(), entityId, tenantId);
233 } 239 }
234 } 240 }
235 241
@@ -239,7 +245,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh @@ -239,7 +245,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
239 245
240 private void onTellNext(TbMsg msg, RuleNodeId originatorNodeId, Set<String> relationTypes, String failureMessage) { 246 private void onTellNext(TbMsg msg, RuleNodeId originatorNodeId, Set<String> relationTypes, String failureMessage) {
241 try { 247 try {
242 - checkActive(); 248 + checkActive(msg);
243 EntityId entityId = msg.getOriginator(); 249 EntityId entityId = msg.getOriginator();
244 TopicPartitionInfo tpi = systemContext.resolve(ServiceType.TB_RULE_ENGINE, tenantId, entityId); 250 TopicPartitionInfo tpi = systemContext.resolve(ServiceType.TB_RULE_ENGINE, tenantId, entityId);
245 List<RuleNodeRelation> relations = nodeRoutes.get(originatorNodeId).stream() 251 List<RuleNodeRelation> relations = nodeRoutes.get(originatorNodeId).stream()
@@ -272,6 +278,8 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh @@ -272,6 +278,8 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
272 putToQueue(tpi, msg, callbackWrapper, target); 278 putToQueue(tpi, msg, callbackWrapper, target);
273 } 279 }
274 } 280 }
  281 + } catch (RuleNodeException rne) {
  282 + msg.getCallback().onFailure(rne);
275 } catch (Exception e) { 283 } catch (Exception e) {
276 msg.getCallback().onFailure(new RuleEngineException("onTellNext - " + e.getMessage())); 284 msg.getCallback().onFailure(new RuleEngineException("onTellNext - " + e.getMessage()));
277 } 285 }
@@ -333,4 +341,9 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh @@ -333,4 +341,9 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
333 } 341 }
334 } 342 }
335 343
  344 + @Override
  345 + protected RuleNodeException getInactiveException() {
  346 + RuleNode firstRuleNode = firstNode != null ? firstNode.getSelf() : null;
  347 + return new RuleNodeException("Rule Chain is not active! Failed to initialize.", ruleChainName, firstRuleNode);
  348 + }
336 } 349 }
@@ -27,12 +27,14 @@ import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; @@ -27,12 +27,14 @@ import org.thingsboard.server.common.msg.queue.PartitionChangeMsg;
27 27
28 public class RuleNodeActor extends ComponentActor<RuleNodeId, RuleNodeActorMessageProcessor> { 28 public class RuleNodeActor extends ComponentActor<RuleNodeId, RuleNodeActorMessageProcessor> {
29 29
  30 + private final String ruleChainName;
30 private final RuleChainId ruleChainId; 31 private final RuleChainId ruleChainId;
31 32
32 - private RuleNodeActor(ActorSystemContext systemContext, TenantId tenantId, RuleChainId ruleChainId, RuleNodeId ruleNodeId) { 33 + private RuleNodeActor(ActorSystemContext systemContext, TenantId tenantId, RuleChainId ruleChainId, String ruleChainName, RuleNodeId ruleNodeId) {
33 super(systemContext, tenantId, ruleNodeId); 34 super(systemContext, tenantId, ruleNodeId);
  35 + this.ruleChainName = ruleChainName;
34 this.ruleChainId = ruleChainId; 36 this.ruleChainId = ruleChainId;
35 - setProcessor(new RuleNodeActorMessageProcessor(tenantId, ruleChainId, ruleNodeId, systemContext, 37 + setProcessor(new RuleNodeActorMessageProcessor(tenantId, this.ruleChainName, ruleNodeId, systemContext,
36 context().parent(), context().self())); 38 context().parent(), context().self()));
37 } 39 }
38 40
@@ -96,19 +98,21 @@ public class RuleNodeActor extends ComponentActor<RuleNodeId, RuleNodeActorMessa @@ -96,19 +98,21 @@ public class RuleNodeActor extends ComponentActor<RuleNodeId, RuleNodeActorMessa
96 98
97 private final TenantId tenantId; 99 private final TenantId tenantId;
98 private final RuleChainId ruleChainId; 100 private final RuleChainId ruleChainId;
  101 + private final String ruleChainName;
99 private final RuleNodeId ruleNodeId; 102 private final RuleNodeId ruleNodeId;
100 103
101 - public ActorCreator(ActorSystemContext context, TenantId tenantId, RuleChainId ruleChainId, RuleNodeId ruleNodeId) { 104 + public ActorCreator(ActorSystemContext context, TenantId tenantId, RuleChainId ruleChainId, String ruleChainName, RuleNodeId ruleNodeId) {
102 super(context); 105 super(context);
103 this.tenantId = tenantId; 106 this.tenantId = tenantId;
104 this.ruleChainId = ruleChainId; 107 this.ruleChainId = ruleChainId;
  108 + this.ruleChainName = ruleChainName;
105 this.ruleNodeId = ruleNodeId; 109 this.ruleNodeId = ruleNodeId;
106 110
107 } 111 }
108 112
109 @Override 113 @Override
110 public RuleNodeActor create() throws Exception { 114 public RuleNodeActor create() throws Exception {
111 - return new RuleNodeActor(context, tenantId, ruleChainId, ruleNodeId); 115 + return new RuleNodeActor(context, tenantId, ruleChainId, ruleChainName, ruleNodeId);
112 } 116 }
113 } 117 }
114 118
@@ -17,37 +17,33 @@ package org.thingsboard.server.actors.ruleChain; @@ -17,37 +17,33 @@ package org.thingsboard.server.actors.ruleChain;
17 17
18 import akka.actor.ActorContext; 18 import akka.actor.ActorContext;
19 import akka.actor.ActorRef; 19 import akka.actor.ActorRef;
20 -import org.thingsboard.rule.engine.api.TbContext;  
21 import org.thingsboard.rule.engine.api.TbNode; 20 import org.thingsboard.rule.engine.api.TbNode;
22 import org.thingsboard.rule.engine.api.TbNodeConfiguration; 21 import org.thingsboard.rule.engine.api.TbNodeConfiguration;
23 import org.thingsboard.server.actors.ActorSystemContext; 22 import org.thingsboard.server.actors.ActorSystemContext;
24 import org.thingsboard.server.actors.shared.ComponentMsgProcessor; 23 import org.thingsboard.server.actors.shared.ComponentMsgProcessor;
25 -import org.thingsboard.server.common.data.id.RuleChainId;  
26 import org.thingsboard.server.common.data.id.RuleNodeId; 24 import org.thingsboard.server.common.data.id.RuleNodeId;
27 import org.thingsboard.server.common.data.id.TenantId; 25 import org.thingsboard.server.common.data.id.TenantId;
28 import org.thingsboard.server.common.data.plugin.ComponentLifecycleState; 26 import org.thingsboard.server.common.data.plugin.ComponentLifecycleState;
29 import org.thingsboard.server.common.data.rule.RuleNode; 27 import org.thingsboard.server.common.data.rule.RuleNode;
30 import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; 28 import org.thingsboard.server.common.msg.queue.PartitionChangeMsg;
31 -import org.thingsboard.server.dao.rule.RuleChainService; 29 +import org.thingsboard.server.common.msg.queue.RuleNodeException;
32 30
33 /** 31 /**
34 * @author Andrew Shvayka 32 * @author Andrew Shvayka
35 */ 33 */
36 public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNodeId> { 34 public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNodeId> {
37 35
38 - private final ActorRef parent; 36 + private final String ruleChainName;
39 private final ActorRef self; 37 private final ActorRef self;
40 - private final RuleChainService service;  
41 private RuleNode ruleNode; 38 private RuleNode ruleNode;
42 private TbNode tbNode; 39 private TbNode tbNode;
43 private DefaultTbContext defaultCtx; 40 private DefaultTbContext defaultCtx;
44 41
45 - RuleNodeActorMessageProcessor(TenantId tenantId, RuleChainId ruleChainId, RuleNodeId ruleNodeId, ActorSystemContext systemContext 42 + RuleNodeActorMessageProcessor(TenantId tenantId, String ruleChainName, RuleNodeId ruleNodeId, ActorSystemContext systemContext
46 , ActorRef parent, ActorRef self) { 43 , ActorRef parent, ActorRef self) {
47 super(systemContext, tenantId, ruleNodeId); 44 super(systemContext, tenantId, ruleNodeId);
48 - this.parent = parent; 45 + this.ruleChainName = ruleChainName;
49 this.self = self; 46 this.self = self;
50 - this.service = systemContext.getRuleChainService();  
51 this.ruleNode = systemContext.getRuleChainService().findRuleNodeById(tenantId, entityId); 47 this.ruleNode = systemContext.getRuleChainService().findRuleNodeById(tenantId, entityId);
52 this.defaultCtx = new DefaultTbContext(systemContext, new RuleNodeCtx(tenantId, parent, self, ruleNode)); 48 this.defaultCtx = new DefaultTbContext(systemContext, new RuleNodeCtx(tenantId, parent, self, ruleNode));
53 } 49 }
@@ -63,8 +59,8 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod @@ -63,8 +59,8 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod
63 @Override 59 @Override
64 public void onUpdate(ActorContext context) throws Exception { 60 public void onUpdate(ActorContext context) throws Exception {
65 RuleNode newRuleNode = systemContext.getRuleChainService().findRuleNodeById(tenantId, entityId); 61 RuleNode newRuleNode = systemContext.getRuleChainService().findRuleNodeById(tenantId, entityId);
66 - boolean restartRequired = !(ruleNode.getType().equals(newRuleNode.getType())  
67 - && ruleNode.getConfiguration().equals(newRuleNode.getConfiguration())); 62 + boolean restartRequired = state != ComponentLifecycleState.ACTIVE ||
  63 + !(ruleNode.getType().equals(newRuleNode.getType()) && ruleNode.getConfiguration().equals(newRuleNode.getConfiguration()));
68 this.ruleNode = newRuleNode; 64 this.ruleNode = newRuleNode;
69 this.defaultCtx.updateSelf(newRuleNode); 65 this.defaultCtx.updateSelf(newRuleNode);
70 if (restartRequired) { 66 if (restartRequired) {
@@ -91,7 +87,7 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod @@ -91,7 +87,7 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod
91 } 87 }
92 88
93 public void onRuleToSelfMsg(RuleNodeToSelfMsg msg) throws Exception { 89 public void onRuleToSelfMsg(RuleNodeToSelfMsg msg) throws Exception {
94 - checkActive(); 90 + checkActive(msg.getMsg());
95 if (ruleNode.isDebugMode()) { 91 if (ruleNode.isDebugMode()) {
96 systemContext.persistDebugInput(tenantId, entityId, msg.getMsg(), "Self"); 92 systemContext.persistDebugInput(tenantId, entityId, msg.getMsg(), "Self");
97 } 93 }
@@ -103,7 +99,7 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod @@ -103,7 +99,7 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod
103 } 99 }
104 100
105 void onRuleChainToRuleNodeMsg(RuleChainToRuleNodeMsg msg) throws Exception { 101 void onRuleChainToRuleNodeMsg(RuleChainToRuleNodeMsg msg) throws Exception {
106 - checkActive(); 102 + checkActive(msg.getMsg());
107 if (ruleNode.isDebugMode()) { 103 if (ruleNode.isDebugMode()) {
108 systemContext.persistDebugInput(tenantId, entityId, msg.getMsg(), msg.getFromRelationType()); 104 systemContext.persistDebugInput(tenantId, entityId, msg.getMsg(), msg.getFromRelationType());
109 } 105 }
@@ -129,4 +125,8 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod @@ -129,4 +125,8 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod
129 return tbNode; 125 return tbNode;
130 } 126 }
131 127
  128 + @Override
  129 + protected RuleNodeException getInactiveException() {
  130 + return new RuleNodeException("Rule Node is not active! Failed to initialize.", ruleChainName, ruleNode);
  131 + }
132 } 132 }
@@ -22,7 +22,10 @@ import org.thingsboard.server.actors.stats.StatsPersistTick; @@ -22,7 +22,10 @@ import org.thingsboard.server.actors.stats.StatsPersistTick;
22 import org.thingsboard.server.common.data.id.EntityId; 22 import org.thingsboard.server.common.data.id.EntityId;
23 import org.thingsboard.server.common.data.id.TenantId; 23 import org.thingsboard.server.common.data.id.TenantId;
24 import org.thingsboard.server.common.data.plugin.ComponentLifecycleState; 24 import org.thingsboard.server.common.data.plugin.ComponentLifecycleState;
  25 +import org.thingsboard.server.common.msg.TbMsg;
25 import org.thingsboard.server.common.msg.queue.PartitionChangeMsg; 26 import org.thingsboard.server.common.msg.queue.PartitionChangeMsg;
  27 +import org.thingsboard.server.common.msg.queue.RuleEngineException;
  28 +import org.thingsboard.server.common.msg.queue.RuleNodeException;
26 29
27 @Slf4j 30 @Slf4j
28 public abstract class ComponentMsgProcessor<T extends EntityId> extends AbstractContextAwareMsgProcessor { 31 public abstract class ComponentMsgProcessor<T extends EntityId> extends AbstractContextAwareMsgProcessor {
@@ -74,11 +77,17 @@ public abstract class ComponentMsgProcessor<T extends EntityId> extends Abstract @@ -74,11 +77,17 @@ public abstract class ComponentMsgProcessor<T extends EntityId> extends Abstract
74 schedulePeriodicMsgWithDelay(context, new StatsPersistTick(), statsPersistFrequency, statsPersistFrequency); 77 schedulePeriodicMsgWithDelay(context, new StatsPersistTick(), statsPersistFrequency, statsPersistFrequency);
75 } 78 }
76 79
77 - protected void checkActive() { 80 + protected void checkActive(TbMsg tbMsg) throws RuleNodeException {
78 if (state != ComponentLifecycleState.ACTIVE) { 81 if (state != ComponentLifecycleState.ACTIVE) {
79 log.debug("Component is not active. Current state [{}] for processor [{}][{}] tenant [{}]", state, entityId.getEntityType(), entityId, tenantId); 82 log.debug("Component is not active. Current state [{}] for processor [{}][{}] tenant [{}]", state, entityId.getEntityType(), entityId, tenantId);
80 - throw new IllegalStateException("Rule chain is not active! " + entityId + " - " + tenantId); 83 + RuleNodeException ruleNodeException = getInactiveException();
  84 + if (tbMsg != null) {
  85 + tbMsg.getCallback().onFailure(ruleNodeException);
  86 + }
  87 + throw ruleNodeException;
81 } 88 }
82 } 89 }
83 90
  91 + abstract protected RuleNodeException getInactiveException();
  92 +
84 } 93 }
@@ -36,9 +36,15 @@ public class RuleNodeException extends RuleEngineException { @@ -36,9 +36,15 @@ public class RuleNodeException extends RuleEngineException {
36 public RuleNodeException(String message, String ruleChainName, RuleNode ruleNode) { 36 public RuleNodeException(String message, String ruleChainName, RuleNode ruleNode) {
37 super(message); 37 super(message);
38 this.ruleChainName = ruleChainName; 38 this.ruleChainName = ruleChainName;
39 - this.ruleNodeName = ruleNode.getName();  
40 - this.ruleChainId = ruleNode.getRuleChainId();  
41 - this.ruleNodeId = ruleNode.getId(); 39 + if (ruleNode != null) {
  40 + this.ruleNodeName = ruleNode.getName();
  41 + this.ruleChainId = ruleNode.getRuleChainId();
  42 + this.ruleNodeId = ruleNode.getId();
  43 + } else {
  44 + ruleNodeName = "Unknown";
  45 + ruleChainId = new RuleChainId(RuleChainId.NULL_UUID);
  46 + ruleNodeId = new RuleNodeId(RuleNodeId.NULL_UUID);
  47 + }
42 } 48 }
43 49
44 public String toJsonString() { 50 public String toJsonString() {