zipkin.autoconfigure.metrics.PrometheusMetricsAutoConfiguration.java Source code

Java tutorial

Introduction

Here is the source code for zipkin.autoconfigure.metrics.PrometheusMetricsAutoConfiguration.java

Source

/**
 * Copyright 2015-2016 The OpenZipkin Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

package zipkin.autoconfigure.metrics;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.endpoint.PublicMetrics;
import org.springframework.boot.actuate.metrics.Metric;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.Collection;
import java.util.regex.Pattern;

@RestController
@RequestMapping("/prometheus")
public class PrometheusMetricsAutoConfiguration {

    private static final Pattern SANITIZE_PREFIX_PATTERN = Pattern.compile("^[^a-zA-Z_]");
    private static final Pattern SANITIZE_BODY_PATTERN = Pattern.compile("[^a-zA-Z0-9_]");

    private final Collection<PublicMetrics> publicMetrics;

    @Autowired
    public PrometheusMetricsAutoConfiguration(Collection<PublicMetrics> publicMetrics) {
        this.publicMetrics = publicMetrics;
    }

    private static String sanitizeMetricName(String metricName) {
        return SANITIZE_BODY_PATTERN.matcher(SANITIZE_PREFIX_PATTERN.matcher(metricName).replaceFirst("_"))
                .replaceAll("_");
    }

    @RequestMapping(method = RequestMethod.GET)
    public ResponseEntity<String> prometheusMetrics() {
        StringBuilder sb = new StringBuilder();

        for (PublicMetrics publicMetrics : this.publicMetrics) {
            for (Metric<?> metric : publicMetrics.metrics()) {
                final String sanitizedName = sanitizeMetricName(metric.getName());
                final String type = typeForName(sanitizedName);
                final String metricName = metricName(sanitizedName, type);
                double value = metric.getValue().doubleValue();

                sb.append(String.format("#TYPE %s %s\n", metricName, type));
                sb.append(String.format("#HELP %s %s\n", metricName, metricName));
                sb.append(String.format("%s %s\n", metricName, prometheusDouble(value)));
            }
        }
        return ResponseEntity.ok().contentType(MediaType.parseMediaType("text/plain; version=0.0.4; charset=utf-8"))
                .body(sb.toString());

    }

    private String prometheusDouble(double value) {
        if (value == Double.POSITIVE_INFINITY) {
            return "+Inf";
        } else if (value == Double.NEGATIVE_INFINITY) {
            return "-Inf";
        } else {
            return String.valueOf(value);
        }
    }

    private String metricName(String name, String type) {
        switch (type) {
        case "counter":
            return name.replaceFirst("^counter_", "");
        case "gauge":
            return name.replaceFirst("^gauge_", "");
        default:
            return name;
        }
    }

    private String typeForName(String name) {
        if (name.startsWith("gauge")) {
            return "gauge";
        }
        if (name.startsWith("counter")) {
            return "counter";
        }

        return "gauge";
    }
}