outbound.go
func (response *OutboundCallResponse) doneReading(unexpected error) {
	now := response.timeNow()

	isSuccess := unexpected == nil && !response.ApplicationError()
	lastAttempt := isSuccess || !response.requestState.HasRetries(unexpected)

	// TODO how should this work with retries?
	if span := response.span; span != nil {
		if unexpected != nil {
			span.LogEventWithPayload("error", unexpected)
		}
		if !isSuccess && lastAttempt {
			ext.Error.Set(span, true)
		}
		span.FinishWithOptions(opentracing.FinishOptions{FinishTime: now})
	}

	latency := now.Sub(response.startedAt)
	response.statsReporter.RecordTimer("outbound.calls.per-attempt.latency", response.commonStatsTags, latency)
	if lastAttempt {
		requestLatency := response.requestState.SinceStart(now, latency)
		response.statsReporter.RecordTimer("outbound.calls.latency", response.commonStatsTags, requestLatency)
	}
	if retryCount := response.requestState.RetryCount(); retryCount > 0 {
		retryTags := cloneTags(response.commonStatsTags)
		retryTags["retry-count"] = fmt.Sprint(retryCount)
		response.statsReporter.IncCounter("outbound.calls.retries", retryTags, 1)
	}

	if unexpected != nil {
		// TODO(prashant): Report the error code type as per metrics doc and enable.
		// response.statsReporter.IncCounter("outbound.calls.system-errors", response.commonStatsTags, 1)
	} else if response.ApplicationError() {
		// TODO(prashant): Figure out how to add "type" to tags, which TChannel does not know about.
		response.statsReporter.IncCounter("outbound.calls.per-attempt.app-errors", response.commonStatsTags, 1)
		if lastAttempt {
			response.statsReporter.IncCounter("outbound.calls.app-errors", response.commonStatsTags, 1)
		}
	} else {
		response.statsReporter.IncCounter("outbound.calls.success", response.commonStatsTags, 1)
	}

	response.mex.shutdown()
}
func (response *OutboundCallResponse) doneReading(unexpected error) {
	now := response.timeNow()

	isSuccess := unexpected == nil && !response.ApplicationError()
	lastAttempt := isSuccess || !response.requestState.HasRetries(unexpected)

	// TODO how should this work with retries?
	if span := response.span; span != nil {
		if unexpected != nil {
			span.LogEventWithPayload("error", unexpected)
		}
		if !isSuccess && lastAttempt {
			ext.Error.Set(span, true)
		}
		span.FinishWithOptions(opentracing.FinishOptions{FinishTime: now})
	}

	latency := now.Sub(response.startedAt)
	response.statsReporter.RecordTimer("outbound.calls.per-attempt.latency", response.commonStatsTags, latency)
	if lastAttempt {
		requestLatency := response.requestState.SinceStart(now, latency)
		response.statsReporter.RecordTimer("outbound.calls.latency", response.commonStatsTags, requestLatency)
	}
	if retryCount := response.requestState.RetryCount(); retryCount > 0 {
		retryTags := cloneTags(response.commonStatsTags)
		retryTags["retry-count"] = fmt.Sprint(retryCount)
		response.statsReporter.IncCounter("outbound.calls.retries", retryTags, 1)
	}

	if unexpected != nil {
		// TODO(prashant): Report the error code type as per metrics doc and enable.
		// response.statsReporter.IncCounter("outbound.calls.system-errors", response.commonStatsTags, 1)
	} else if response.ApplicationError() {
		// TODO(prashant): Figure out how to add "type" to tags, which TChannel does not know about.
		response.statsReporter.IncCounter("outbound.calls.per-attempt.app-errors", response.commonStatsTags, 1)
		if lastAttempt {
			response.statsReporter.IncCounter("outbound.calls.app-errors", response.commonStatsTags, 1)
		}
	} else {
		response.statsReporter.IncCounter("outbound.calls.success", response.commonStatsTags, 1)
	}

	response.mex.shutdown()
}
// doneReading shuts down the message exchange for this call.
// For outgoing calls, the last message is reading the call response.