AbstractInvokeCallback implements InvokeCallback { protected void recordClientElapseTime() { if (context != null) { Long startTime = (Long) context.removeAttachment(RpcConstants.INTERNAL_KEY_CLIENT_SEND_TIME); if (startTime != null) { context.setAttachment(RpcConstants.INTERNAL_KEY_CLIENT_ELAPSE, RpcRuntimeContext.now() - startTime); } } } protected  AbstractInvokeCallback(ConsumerConfig consumerConfig, ProviderInfo providerInfo, SofaRequest request,
                                     RpcInternalContext context, ClassLoader classLoader);   }
@Test public void testRecordClientElapseTime() { BoltInvokerCallback invokerCallback = new BoltInvokerCallback(null, null, null, null, null, null); invokerCallback.recordClientElapseTime(); Long elapse = (Long) RpcInternalContext.getContext().getAttachment(RpcConstants.INTERNAL_KEY_CLIENT_ELAPSE); Assert.assertNull(elapse); RpcInternalContext context = RpcInternalContext.getContext(); invokerCallback = new BoltInvokerCallback(null, null, null, null, context, null); invokerCallback.recordClientElapseTime(); elapse = (Long) context.getAttachment(RpcConstants.INTERNAL_KEY_CLIENT_ELAPSE); Assert.assertNull(elapse); context.setAttachment(RpcConstants.INTERNAL_KEY_CLIENT_SEND_TIME, RpcRuntimeContext.now() - 1000); invokerCallback.recordClientElapseTime(); elapse = (Long) context.getAttachment(RpcConstants.INTERNAL_KEY_CLIENT_ELAPSE); Assert.assertNotNull(elapse); }