public List<MetricsPacket.Builder> getMetricsAsBuilders(List<VespaService> services, Instant startTime, ConsumerId consumerId) {
        if (services.isEmpty()) return List.of();

        log.log(FINE, () -> "Updating services prior to fetching metrics, number of services= " + services.size());
        vespaServices.updateServices(services);

        List<MetricsPacket.Builder> result = vespaMetrics.getMetrics(services, consumerId);
        log.log(FINE, () -> "Got " + result.size() + " metrics packets for vespa services.");

        purgeStaleMetrics();
        List<MetricsPacket.Builder> externalPackets = externalMetrics.getMetrics().stream()
                .filter(MetricsPacket.Builder::hasMetrics)
                .toList();
        log.log(FINE, () -> "Got " + externalPackets.size() + " external metrics packets with whitelisted metrics.");

        result.addAll(externalPackets);

        Map<DimensionId, String> globalDims = getGlobalDimensions();
        return result.stream()
                .map(builder -> builder.putDimensionsIfAbsent(globalDims))
                .map(builder -> builder.putDimensionsIfAbsent(extraDimensions))
                .map(builder -> adjustTimestamp(builder, startTime))
                .toList();
    }
Returns the metrics for the given services, in mutable state for further processing.
NOTE: Use {@link #getMetrics(List, Instant)} instead, unless further processing of the metrics is necessary.
metrics-proxy/src/main/java/ai/vespa/metricsproxy/core/MetricsManager.java