All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.quarkus.micrometer.runtime.registry.json.JsonExporter Maven / Gradle / Ivy

Go to download

Instrument the runtime and your application with dimensional metrics using Micrometer.

There is a newer version: 3.17.5
Show newest version
package io.quarkus.micrometer.runtime.registry.json;

import static io.quarkus.jsonp.JsonProviderHolder.jsonProvider;

import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import jakarta.json.JsonObject;
import jakarta.json.JsonObjectBuilder;
import jakarta.json.JsonValue;
import jakarta.json.JsonWriter;
import jakarta.json.stream.JsonGenerator;

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.DistributionSummary;
import io.micrometer.core.instrument.FunctionCounter;
import io.micrometer.core.instrument.FunctionTimer;
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.LongTaskTimer;
import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.Tag;
import io.micrometer.core.instrument.TimeGauge;
import io.micrometer.core.instrument.Timer;
import io.micrometer.core.instrument.distribution.HistogramSnapshot;
import io.micrometer.core.instrument.distribution.ValueAtPercentile;

public class JsonExporter {

    private static final Map JSON_CONFIG = Collections.singletonMap(JsonGenerator.PRETTY_PRINTING, true);

    public JsonExporter() {
    }

    public StringBuilder exportEverything(JsonMeterRegistry meterRegistry) {
        JsonObjectBuilder root = jsonProvider().createObjectBuilder();
        List gauges = new ArrayList<>();
        List counters = new ArrayList<>();
        List timeGauges = new ArrayList<>();
        List functionCounters = new ArrayList<>();
        List timers = new ArrayList<>();
        List longTaskTimers = new ArrayList<>();
        List functionTimers = new ArrayList<>();
        List distributionSummaries = new ArrayList<>();
        List meters = new ArrayList<>();
        meterRegistry.getMeters().forEach(meter -> meter.match(gauges::add,
                counters::add,
                timers::add,
                distributionSummaries::add,
                longTaskTimers::add,
                timeGauges::add,
                functionCounters::add,
                functionTimers::add,
                meters::add));
        exportCounters(counters).forEach(root::add);
        exportGauges(gauges).forEach(root::add);
        exportTimeGauges(timeGauges).forEach(root::add);
        exportFunctionCounters(functionCounters).forEach(root::add);
        exportTimers(timers).forEach(root::add);
        exportLongTaskTimers(longTaskTimers).forEach(root::add);
        exportFunctionTimers(functionTimers).forEach(root::add);
        exportDistributionSummaries(distributionSummaries).forEach(root::add);
        return stringify(root.build());
    }

    private Map exportGauges(Collection gauges) {
        Map result = new HashMap(gauges.size());
        for (Gauge g : gauges) {
            double value = g.value();
            if (Double.isFinite(value)) {
                result.put(createExportKey(g.getId()), jsonProvider().createValue(value));
            }
        }
        return result;
    }

    private Map exportTimeGauges(Collection timeGauges) {
        Map result = new HashMap(timeGauges.size());
        for (TimeGauge g : timeGauges) {
            double value = g.value();
            if (Double.isFinite(value)) {
                result.put(createExportKey(g.getId()), jsonProvider().createValue(value));
            }
        }
        return result;
    }

    private Map exportCounters(Collection counters) {
        return counters.stream()
                .collect(Collectors.toMap(counter -> createExportKey(counter.getId()),
                        counter -> jsonProvider().createValue(counter.count())));
    }

    private Map exportFunctionCounters(Collection counters) {
        return counters.stream()
                .collect(Collectors.toMap(counter -> createExportKey(counter.getId()),
                        counter -> jsonProvider().createValue(counter.count())));
    }

    private Map exportTimers(Collection timers) {
        Map> groups = timers.stream().collect(Collectors.groupingBy(timer -> timer.getId().getName()));
        Map result = new HashMap<>();
        for (Map.Entry> group : groups.entrySet()) {
            JsonObjectBuilder builder = jsonProvider().createObjectBuilder();
            for (Timer timer : group.getValue()) {
                builder.add(createExportKey("count", timer.getId()), timer.count());
                builder.add(createExportKey("elapsedTime", timer.getId()), timer.totalTime(timer.baseTimeUnit()));
            }
            result.put(group.getKey(), builder.build());
        }
        return result;
    }

    private Map exportLongTaskTimers(Collection timers) {
        Map> groups = timers.stream()
                .collect(Collectors.groupingBy(timer -> timer.getId().getName()));
        Map result = new HashMap<>();
        for (Map.Entry> group : groups.entrySet()) {
            JsonObjectBuilder builder = jsonProvider().createObjectBuilder();
            for (LongTaskTimer timer : group.getValue()) {
                builder.add(createExportKey("activeTasks", timer.getId()), timer.activeTasks());
                builder.add(createExportKey("duration", timer.getId()), timer.duration(timer.baseTimeUnit()));
                builder.add(createExportKey("max", timer.getId()), timer.max(timer.baseTimeUnit()));
                builder.add(createExportKey("mean", timer.getId()), timer.mean(timer.baseTimeUnit()));
            }
            result.put(group.getKey(), builder.build());
        }
        return result;
    }

    private Map exportFunctionTimers(Collection timers) {
        Map> groups = timers.stream()
                .collect(Collectors.groupingBy(timer -> timer.getId().getName()));
        Map result = new HashMap<>();
        for (Map.Entry> group : groups.entrySet()) {
            JsonObjectBuilder builder = jsonProvider().createObjectBuilder();
            for (FunctionTimer timer : group.getValue()) {
                builder.add(createExportKey("count", timer.getId()), timer.count());
                builder.add(createExportKey("elapsedTime", timer.getId()), timer.totalTime(timer.baseTimeUnit()));
            }
            result.put(group.getKey(), builder.build());
        }
        return result;
    }

    private Map exportDistributionSummaries(Collection distributionSummaries) {
        Map> groups = distributionSummaries.stream()
                .collect(Collectors.groupingBy(summary -> summary.getId().getName()));
        Map result = new HashMap<>();
        for (Map.Entry> group : groups.entrySet()) {
            JsonObjectBuilder builder = jsonProvider().createObjectBuilder();
            for (DistributionSummary summary : group.getValue()) {
                HistogramSnapshot snapshot = summary.takeSnapshot();
                if (summary instanceof JsonDistributionSummary) {
                    double min = ((JsonDistributionSummary) summary).min();
                    // if there are no samples yet, show 0 as the min
                    builder.add(createExportKey("min", summary.getId()), !Double.isNaN(min) ? min : 0);
                }
                builder.add(createExportKey("count", summary.getId()), snapshot.count());
                builder.add(createExportKey("max", summary.getId()), snapshot.max());
                builder.add(createExportKey("mean", summary.getId()), snapshot.mean());
                for (ValueAtPercentile valueAtPercentile : snapshot.percentileValues()) {
                    if (Math.abs(valueAtPercentile.percentile() - 0.999) < 0.000001) {
                        builder.add(createExportKey("p999", summary.getId()),
                                valueAtPercentile.value());
                    } else {
                        builder.add(
                                createExportKey("p" + (int) Math.floor(valueAtPercentile.percentile() * 100), summary.getId()),
                                valueAtPercentile.value());
                    }
                }
            }
            result.put(group.getKey(), builder.build());
        }
        return result;
    }

    private StringBuilder stringify(JsonObject obj) {
        StringWriter out = new StringWriter();
        try (JsonWriter writer = jsonProvider().createWriterFactory(JSON_CONFIG).createWriter(out)) {
            writer.writeObject(obj);
        }
        return new StringBuilder(out.toString());
    }

    private String createExportKey(Meter.Id id) {
        return id.getName() + createTagsString(id.getTags());
    }

    private String createExportKey(String componentKey, Meter.Id id) {
        return componentKey + createTagsString(id.getTags());
    }

    private String createTagsString(List tags) {
        if (tags == null || tags.isEmpty()) {
            return "";
        } else {
            return ";" + tags.stream()
                    .map(tag -> tag.getKey() + "=" + tag.getValue()
                            .replace(";", "_"))
                    .collect(Collectors.joining(";"));
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy