Refactor the mechanism of recording error in Entry and StatisticSlot
* Also polish related complete callbacks Signed-off-by: Eric Zhao <sczyh16@gmail.com>
This commit is contained in:
parent
7f0771df5c
commit
7f3165740a
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package com.alibaba.csp.sentinel;
|
||||
|
||||
import com.alibaba.csp.sentinel.slots.block.BlockException;
|
||||
import com.alibaba.csp.sentinel.util.TimeUtil;
|
||||
import com.alibaba.csp.sentinel.context.ContextUtil;
|
||||
import com.alibaba.csp.sentinel.node.Node;
|
||||
|
|
@ -44,6 +45,7 @@ import com.alibaba.csp.sentinel.context.Context;
|
|||
* @author qinan.qn
|
||||
* @author jialiang.linjl
|
||||
* @author leyou(lihao)
|
||||
* @author Eric Zhao
|
||||
* @see SphU
|
||||
* @see Context
|
||||
* @see ContextUtil
|
||||
|
|
@ -52,18 +54,23 @@ public abstract class Entry implements AutoCloseable {
|
|||
|
||||
private static final Object[] OBJECTS0 = new Object[0];
|
||||
|
||||
private long createTime;
|
||||
private final long createTimestamp;
|
||||
private long completeTimestamp;
|
||||
|
||||
private Node curNode;
|
||||
/**
|
||||
* {@link Node} of the specific origin, Usually the origin is the Service Consumer.
|
||||
*/
|
||||
private Node originNode;
|
||||
|
||||
private Throwable error;
|
||||
protected ResourceWrapper resourceWrapper;
|
||||
private BlockException blockError;
|
||||
|
||||
protected final ResourceWrapper resourceWrapper;
|
||||
|
||||
public Entry(ResourceWrapper resourceWrapper) {
|
||||
this.resourceWrapper = resourceWrapper;
|
||||
this.createTime = TimeUtil.currentTimeMillis();
|
||||
this.createTimestamp = TimeUtil.currentTimeMillis();
|
||||
}
|
||||
|
||||
public ResourceWrapper getResourceWrapper() {
|
||||
|
|
@ -119,8 +126,17 @@ public abstract class Entry implements AutoCloseable {
|
|||
*/
|
||||
public abstract Node getLastNode();
|
||||
|
||||
public long getCreateTime() {
|
||||
return createTime;
|
||||
public long getCreateTimestamp() {
|
||||
return createTimestamp;
|
||||
}
|
||||
|
||||
public long getCompleteTimestamp() {
|
||||
return completeTimestamp;
|
||||
}
|
||||
|
||||
public Entry setCompleteTimestamp(long completeTimestamp) {
|
||||
this.completeTimestamp = completeTimestamp;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Node getCurNode() {
|
||||
|
|
@ -131,6 +147,15 @@ public abstract class Entry implements AutoCloseable {
|
|||
this.curNode = node;
|
||||
}
|
||||
|
||||
public BlockException getBlockError() {
|
||||
return blockError;
|
||||
}
|
||||
|
||||
public Entry setBlockError(BlockException blockError) {
|
||||
this.blockError = blockError;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Throwable getError() {
|
||||
return error;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,14 +14,22 @@ import com.alibaba.csp.sentinel.util.TimeUtil;
|
|||
* @since 1.6.1
|
||||
*/
|
||||
public class MetricExitCallback implements ProcessorSlotExitCallback {
|
||||
|
||||
@Override
|
||||
public void onExit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) {
|
||||
for (MetricExtension m : MetricExtensionProvider.getMetricExtensions()) {
|
||||
if (context.getCurEntry().getError() == null) {
|
||||
long realRt = TimeUtil.currentTimeMillis() - context.getCurEntry().getCreateTime();
|
||||
m.addRt(resourceWrapper.getName(), realRt, args);
|
||||
m.addSuccess(resourceWrapper.getName(), count, args);
|
||||
m.decreaseThreadNum(resourceWrapper.getName(), args);
|
||||
if (context.getCurEntry().getBlockError() != null) {
|
||||
continue;
|
||||
}
|
||||
String resource = resourceWrapper.getName();
|
||||
long realRt = TimeUtil.currentTimeMillis() - context.getCurEntry().getCreateTimestamp();
|
||||
m.addRt(resource, realRt, args);
|
||||
m.addSuccess(resource, count, args);
|
||||
m.decreaseThreadNum(resource, args);
|
||||
|
||||
Throwable ex = context.getCurEntry().getError();
|
||||
if (ex != null) {
|
||||
m.addException(resource, count, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ package com.alibaba.csp.sentinel.slots.statistic;
|
|||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.alibaba.csp.sentinel.config.SentinelConfig;
|
||||
import com.alibaba.csp.sentinel.node.Node;
|
||||
import com.alibaba.csp.sentinel.slotchain.ProcessorSlotEntryCallback;
|
||||
import com.alibaba.csp.sentinel.slotchain.ProcessorSlotExitCallback;
|
||||
import com.alibaba.csp.sentinel.slots.block.flow.PriorityWaitException;
|
||||
|
|
@ -95,7 +95,7 @@ public class StatisticSlot extends AbstractLinkedProcessorSlot<DefaultNode> {
|
|||
}
|
||||
} catch (BlockException e) {
|
||||
// Blocked, set block exception to current entry.
|
||||
context.getCurEntry().setError(e);
|
||||
context.getCurEntry().setBlockError(e);
|
||||
|
||||
// Add block count.
|
||||
node.increaseBlockQps(count);
|
||||
|
|
@ -115,52 +115,31 @@ public class StatisticSlot extends AbstractLinkedProcessorSlot<DefaultNode> {
|
|||
|
||||
throw e;
|
||||
} catch (Throwable e) {
|
||||
// Unexpected error, set error to current entry.
|
||||
// Unexpected internal error, set error to current entry.
|
||||
context.getCurEntry().setError(e);
|
||||
|
||||
// This should not happen.
|
||||
node.increaseExceptionQps(count);
|
||||
if (context.getCurEntry().getOriginNode() != null) {
|
||||
context.getCurEntry().getOriginNode().increaseExceptionQps(count);
|
||||
}
|
||||
|
||||
if (resourceWrapper.getEntryType() == EntryType.IN) {
|
||||
Constants.ENTRY_NODE.increaseExceptionQps(count);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) {
|
||||
DefaultNode node = (DefaultNode)context.getCurNode();
|
||||
Node node = context.getCurNode();
|
||||
|
||||
if (context.getCurEntry().getError() == null) {
|
||||
// Calculate response time (max RT is statisticMaxRt from SentinelConfig).
|
||||
long rt = TimeUtil.currentTimeMillis() - context.getCurEntry().getCreateTime();
|
||||
int maxStatisticRt = SentinelConfig.statisticMaxRt();
|
||||
if (rt > maxStatisticRt) {
|
||||
rt = maxStatisticRt;
|
||||
}
|
||||
if (context.getCurEntry().getBlockError() == null) {
|
||||
// Calculate response time (use completeStatTime as the time of completion).
|
||||
long completeStatTime = TimeUtil.currentTimeMillis();
|
||||
context.getCurEntry().setCompleteTimestamp(completeStatTime);
|
||||
long rt = completeStatTime - context.getCurEntry().getCreateTimestamp();
|
||||
|
||||
Throwable error = context.getCurEntry().getError();
|
||||
|
||||
// Record response time and success count.
|
||||
node.addRtAndSuccess(rt, count);
|
||||
if (context.getCurEntry().getOriginNode() != null) {
|
||||
context.getCurEntry().getOriginNode().addRtAndSuccess(rt, count);
|
||||
}
|
||||
|
||||
node.decreaseThreadNum();
|
||||
|
||||
if (context.getCurEntry().getOriginNode() != null) {
|
||||
context.getCurEntry().getOriginNode().decreaseThreadNum();
|
||||
}
|
||||
|
||||
recordCompleteFor(node, count, rt, error);
|
||||
recordCompleteFor(context.getCurEntry().getOriginNode(), count, rt, error);
|
||||
if (resourceWrapper.getEntryType() == EntryType.IN) {
|
||||
Constants.ENTRY_NODE.addRtAndSuccess(rt, count);
|
||||
Constants.ENTRY_NODE.decreaseThreadNum();
|
||||
recordCompleteFor(Constants.ENTRY_NODE, count, rt, error);
|
||||
}
|
||||
} else {
|
||||
// Error may happen.
|
||||
}
|
||||
|
||||
// Handle exit event with registered exit callback handlers.
|
||||
|
|
@ -171,4 +150,16 @@ public class StatisticSlot extends AbstractLinkedProcessorSlot<DefaultNode> {
|
|||
|
||||
fireExit(context, resourceWrapper, count);
|
||||
}
|
||||
|
||||
private void recordCompleteFor(Node node, int batchCount, long rt, Throwable error) {
|
||||
if (node == null) {
|
||||
return;
|
||||
}
|
||||
node.addRtAndSuccess(rt, batchCount);
|
||||
node.decreaseThreadNum();
|
||||
|
||||
if (error != null && !(error instanceof BlockException)) {
|
||||
node.increaseExceptionQps(batchCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ public class MetricExitCallbackTest extends AbstractTimeBasedTest {
|
|||
|
||||
int deltaMs = 100;
|
||||
when(entry.getError()).thenReturn(null);
|
||||
when(entry.getCreateTime()).thenReturn(curMillis - deltaMs);
|
||||
when(entry.getCreateTimestamp()).thenReturn(curMillis - deltaMs);
|
||||
when(context.getCurEntry()).thenReturn(entry);
|
||||
exitCallback.onExit(context, resourceWrapper, count, args);
|
||||
Assert.assertEquals(prevRt + deltaMs, extension.rt);
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ public class ParamFlowStatisticExitCallback implements ProcessorSlotExitCallback
|
|||
|
||||
@Override
|
||||
public void onExit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) {
|
||||
if (context.getCurEntry().getError() == null) {
|
||||
if (context.getCurEntry().getBlockError() == null) {
|
||||
ParameterMetric parameterMetric = ParameterMetricStorage.getParamMetric(resourceWrapper);
|
||||
|
||||
if (parameterMetric != null) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue