package org.stagemonitor.tracing.metrics;
import com.codahale.metrics.Timer;
import org.stagemonitor.core.Stagemonitor;
import org.stagemonitor.core.metrics.metrics2.Metric2Registry;
import org.stagemonitor.core.metrics.metrics2.MetricName;
import org.stagemonitor.tracing.SpanContextInformation;
import org.stagemonitor.tracing.utils.SpanUtils;
import org.stagemonitor.tracing.wrapper.ClientServerAwareSpanEventListener;
import org.stagemonitor.tracing.wrapper.SpanEventListener;
import org.stagemonitor.tracing.wrapper.SpanEventListenerFactory;
import org.stagemonitor.tracing.wrapper.SpanWrapper;
import org.stagemonitor.util.StringUtils;
import java.util.concurrent.TimeUnit;
import static org.stagemonitor.core.metrics.metrics2.MetricName.name;
public class ExternalRequestMetricsSpanEventListener extends ClientServerAwareSpanEventListener {
private final Metric2Registry metricRegistry;
public static final String EXTERNAL_REQUEST_METHOD = "method";
private static final MetricName.MetricNameTemplate externalRequestTemplate = name("external_request_response_time")
.templateFor("type", "signature", "method");
private String type;
private String method;
public ExternalRequestMetricsSpanEventListener(Metric2Registry metricRegistry) {
this.metricRegistry = metricRegistry;
}
public static class Factory implements SpanEventListenerFactory {
private final Metric2Registry metricRegistry;
public Factory() {
this(Stagemonitor.getMetric2Registry());
}
public Factory(Metric2Registry metricRegistry) {
this.metricRegistry = metricRegistry;
}
@Override
public SpanEventListener create() {
return new ExternalRequestMetricsSpanEventListener(metricRegistry);
}
}
@Override
public String onSetTag(String key, String value) {
value = super.onSetTag(key, value);
if (SpanUtils.OPERATION_TYPE.equals(key)) {
type = value;
} else if (EXTERNAL_REQUEST_METHOD.equals(key)) {
method = value;
}
return value;
}
@Override
public void onFinish(SpanWrapper spanWrapper, String operationName, long durationNanos) {
if (isClient && StringUtils.isNotEmpty(type) && StringUtils.isNotEmpty(operationName) && StringUtils.isNotEmpty(method)) {
metricRegistry.timer(externalRequestTemplate.build(type, "All", method))
.update(durationNanos, TimeUnit.NANOSECONDS);
final Timer timer = metricRegistry.timer(externalRequestTemplate.build(type, operationName, method));
SpanContextInformation.forSpan(spanWrapper).setTimerForThisRequest(timer);
timer.update(durationNanos, TimeUnit.NANOSECONDS);
final SpanContextInformation parent = SpanContextInformation.forSpan(spanWrapper).getParent();
if (parent != null) {
parent.addExternalRequest(type, durationNanos);
}
}
}
}