static String getPathInfo(RequestLog requestLog) {
    String uri = requestLog.context().path();
    if (!StringUtils.hasText(uri)) return "/";
    return uri.replaceAll("//+", "/")
      .replaceAll("/$", "");
  }
").build(),
      (ctx, req) -> HttpResponse.of(HttpStatus.NOT_FOUND));
  }

  static final class MetricCollectingService extends SimpleDecoratingHttpService {
    final MeterRegistry registry;
    final String metricName;

    MetricCollectingService(HttpService delegate, MeterRegistry registry, String metricName) {
      super(delegate);
      this.registry = registry;
      this.metricName = metricName;
    }

    @Override
    public HttpResponse serve(ServiceRequestContext ctx, HttpRequest req) throws Exception {
      setup(ctx, registry, metricName);
      return unwrap().serve(ctx, req);
    }
  }

  // A variable to make sure setup method is not called twice.
  private static final AttributeKey<Boolean> PROMETHEUS_METRICS_SET =
    AttributeKey.valueOf(Boolean.class, "PROMETHEUS_METRICS_SET");

  @SuppressWarnings("FutureReturnValueIgnored") // no known action to take following .thenAccept
  public static void setup(RequestContext ctx, MeterRegistry registry, String metricName) {
    if (ctx.hasAttr(PROMETHEUS_METRICS_SET)) {
      return;
    }
    ctx.setAttr(PROMETHEUS_METRICS_SET, true);
    ctx.log().whenComplete().thenAccept(log -> getTimeBuilder(log, metricName).register(registry)
      .record(log.totalDurationNanos(), TimeUnit.NANOSECONDS));
  }

  private static Timer.Builder getTimeBuilder(RequestLog requestLog, String metricName) {
    return Timer.builder(metricName)
      .tags(getTags(requestLog))
      .description("Response time histogram")
      .publishPercentileHistogram();
  }

  private static Iterable<Tag> getTags(RequestLog requestLog) {
    return Arrays.asList(Tag.of("method", requestLog.requestHeaders().method().toString())
      , uri(requestLog)
      , Tag.of("status", Integer.toString(requestLog.responseHeaders().status().code()))
    );
  }

  /** Ensure metrics cardinality doesn't blow up on variables
zipkin-server/src/main/java/zipkin2/server/internal/prometheus/ZipkinPrometheusMetricsConfiguration.java