001/* 002 * Copyright © 2025 CUI-OpenSource-Software (info@cuioss.de) 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package de.cuioss.benchmarking.common.metrics; 017 018import de.cuioss.tools.logging.CuiLogger; 019 020import java.io.IOException; 021import java.nio.file.Files; 022import java.nio.file.Path; 023import java.time.Duration; 024import java.time.Instant; 025import java.util.List; 026import java.util.Map; 027 028import static de.cuioss.benchmarking.common.util.BenchmarkingLogMessages.ERROR.FAILED_COLLECT_REALTIME_PROMETHEUS; 029import static de.cuioss.benchmarking.common.util.BenchmarkingLogMessages.INFO.COLLECTING_REALTIME_METRICS; 030import static de.cuioss.benchmarking.common.util.BenchmarkingLogMessages.INFO.REALTIME_METRICS_EXPORTED; 031 032/** 033 * Orchestrator for metrics processing. 034 * Coordinates the transformation and export of real-time Prometheus metrics. 035 * Delegates all transformation logic to BenchmarkMetricsTransformer. 036 */ 037public class MetricsOrchestrator { 038 039 private static final CuiLogger LOGGER = new CuiLogger(MetricsOrchestrator.class); 040 041 private final PrometheusClient prometheusClient; 042 043 /** 044 * Creates a new metrics orchestrator. 045 * 046 * @param prometheusClient PrometheusClient for real-time metrics collection 047 */ 048 public MetricsOrchestrator(PrometheusClient prometheusClient) { 049 this.prometheusClient = prometheusClient; 050 } 051 052 053 /** 054 * Collects real-time metrics from Prometheus for a benchmark execution. 055 * Fetches time-series data, calculates statistics (avg, p50, p95, max), 056 * and exports to JSON format. 057 * 058 * @param benchmarkName Name of the benchmark for file naming 059 * @param startTime Start time of the benchmark execution 060 * @param endTime End time of the benchmark execution 061 * @param outputDir Directory to store the metrics JSON file 062 * @throws IOException if I/O operations fail 063 */ 064 public void collectBenchmarkMetrics(String benchmarkName, Instant startTime, Instant endTime, Path outputDir) 065 throws IOException { 066 LOGGER.info(COLLECTING_REALTIME_METRICS, benchmarkName, startTime, endTime); 067 068 // Define metrics to collect during benchmark execution 069 // Using actual metric names from Prometheus 070 List<String> metricNames = List.of( 071 // CPU metrics 072 "process_cpu_usage", 073 "system_cpu_usage", 074 "system_cpu_count", 075 076 // Memory metrics 077 "jvm_memory_used_bytes", 078 "jvm_memory_committed_bytes", 079 "jvm_memory_max_bytes", 080 081 // Thread metrics 082 "jvm_threads_live_threads", 083 "jvm_threads_daemon_threads", 084 "jvm_threads_peak_threads", 085 086 // GC metrics 087 "jvm_gc_overhead", 088 089 // JWT specific metrics 090 "sheriff_oauth_validation_success_operations_total", 091 "sheriff_oauth_validation_errors_total", 092 "sheriff_oauth_bearer_token_validation_seconds_count", 093 "sheriff_oauth_bearer_token_validation_seconds_sum" 094 ); 095 096 try { 097 // Query Prometheus for metrics within the benchmark time window 098 Duration step = Duration.ofSeconds(2); // 2-second resolution matching scrape interval 099 Map<String, PrometheusClient.TimeSeries> timeSeriesData = 100 prometheusClient.queryRange(metricNames, startTime, endTime, step); 101 102 // Transform time-series data using the new BenchmarkMetricsTransformer 103 BenchmarkMetricsTransformer transformer = new BenchmarkMetricsTransformer(); 104 Map<String, Object> metricsOutput = transformer.transformToServerMetrics( 105 benchmarkName, startTime, endTime, timeSeriesData); 106 107 // Export to JSON file in the format specified in benchmark-metrics.adoc 108 Files.createDirectories(outputDir); 109 String fileName = "%s-server-metrics.json".formatted(benchmarkName); 110 MetricsJsonExporter exporter = new MetricsJsonExporter(outputDir); 111 exporter.exportToFile(fileName, metricsOutput); 112 113 Path outputFile = outputDir.resolve(fileName); 114 LOGGER.info(REALTIME_METRICS_EXPORTED, benchmarkName, outputFile); 115 116 } catch (PrometheusClient.PrometheusException e) { 117 LOGGER.error(e, FAILED_COLLECT_REALTIME_PROMETHEUS, benchmarkName, e.getMessage()); 118 throw new IOException("Failed to collect Prometheus metrics", e); 119 } 120 } 121}