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.config; 017 018import de.cuioss.tools.logging.CuiLogger; 019import org.openjdk.jmh.results.format.ResultFormatType; 020 021import java.io.File; 022 023import static de.cuioss.benchmarking.common.constants.BenchmarkConstants.Files.Directories; 024import static de.cuioss.benchmarking.common.constants.BenchmarkConstants.Integration.Jmh; 025import static de.cuioss.benchmarking.common.util.BenchmarkingLogMessages.WARN.UNKNOWN_RESULT_FORMAT; 026 027/** 028 * Configuration for benchmark report generation. 029 * Contains all report-specific settings that control how benchmark results 030 * are processed and presented. 031 * 032 * <p>Example usage: 033 * <pre>{@code 034 * var reportConfig = ReportConfiguration.builder() 035 * .withBenchmarkType(BenchmarkType.MICRO) 036 * .withThroughputBenchmarkName("measureThroughput") 037 * .withLatencyBenchmarkName("measureAverageTime") 038 * .withResultsDirectory("target/benchmark-results") 039 * .build(); 040 * }</pre> 041 * 042 */ 043public record ReportConfiguration( 044BenchmarkType benchmarkType, 045String throughputBenchmarkName, 046String latencyBenchmarkName, 047String resultsDirectory, 048String resultFile, 049ResultFormatType resultFormat, 050String projectName 051) { 052 private static final CuiLogger LOGGER = new CuiLogger(ReportConfiguration.class); 053 054 055 /** 056 * Creates a builder with default values. 057 * 058 * @return a new builder with default values 059 */ 060 public static Builder builder() { 061 return new Builder(); 062 } 063 064 /** 065 * Creates a builder from this configuration. 066 * 067 * @return a new builder initialized with this configuration's values 068 */ 069 public Builder toBuilder() { 070 return new Builder() 071 .withBenchmarkType(benchmarkType) 072 .withThroughputBenchmarkName(throughputBenchmarkName) 073 .withLatencyBenchmarkName(latencyBenchmarkName) 074 .withResultsDirectory(resultsDirectory) 075 .withResultFile(resultFile) 076 .withResultFormat(resultFormat) 077 .withProjectName(projectName); 078 } 079 080 /** 081 * Gets the result file path, generating one if not explicitly set. 082 * Creates the results directory if it doesn't exist. 083 * 084 * @return the result file path 085 */ 086 public String getOrCreateResultFile() { 087 if (resultFile != null) { 088 return resultFile; 089 } 090 091 // Create results directory if it doesn't exist 092 File dir = new File(resultsDirectory); 093 if (!dir.exists()) { 094 boolean created = dir.mkdirs(); 095 if (!created) { 096 // Directory already exists or could not be created 097 // Log warning if needed, but continue with default path 098 } 099 } 100 101 // Generate result file name based on benchmark type 102 String typePrefix = benchmarkType != null ? benchmarkType.name().toLowerCase() : "benchmark"; 103 return resultsDirectory + "/" + typePrefix + "-result.json"; 104 } 105 106 /** 107 * Builder for ReportConfiguration. 108 */ 109 public static class Builder { 110 private BenchmarkType benchmarkType; 111 private String throughputBenchmarkName; 112 private String latencyBenchmarkName; 113 private String resultsDirectory = Directories.RESULTS_DIR; 114 private String resultFile; 115 private ResultFormatType resultFormat = parseResultFormat(System.getProperty(Jmh.RESULT_FORMAT, "JSON")); 116 private String projectName; 117 118 public Builder withBenchmarkType(BenchmarkType type) { 119 this.benchmarkType = type; 120 return this; 121 } 122 123 public Builder withThroughputBenchmarkName(String name) { 124 this.throughputBenchmarkName = name; 125 return this; 126 } 127 128 public Builder withLatencyBenchmarkName(String name) { 129 this.latencyBenchmarkName = name; 130 return this; 131 } 132 133 public Builder withResultsDirectory(String dir) { 134 this.resultsDirectory = dir; 135 return this; 136 } 137 138 public Builder withResultFile(String file) { 139 this.resultFile = file; 140 return this; 141 } 142 143 public Builder withResultFormat(ResultFormatType format) { 144 this.resultFormat = format; 145 return this; 146 } 147 148 public Builder withProjectName(String name) { 149 this.projectName = name; 150 return this; 151 } 152 153 /** 154 * Builds the configuration. 155 * 156 * @return the built configuration 157 * @throws IllegalArgumentException if required fields are not set 158 */ 159 public ReportConfiguration build() { 160 // Validate required fields 161 if (benchmarkType == null) { 162 throw new IllegalArgumentException("Benchmark type must be set"); 163 } 164 if (throughputBenchmarkName == null || throughputBenchmarkName.isBlank()) { 165 throw new IllegalArgumentException("Throughput benchmark name must be set"); 166 } 167 if (latencyBenchmarkName == null || latencyBenchmarkName.isBlank()) { 168 throw new IllegalArgumentException("Latency benchmark name must be set"); 169 } 170 171 return new ReportConfiguration( 172 benchmarkType, 173 throughputBenchmarkName, 174 latencyBenchmarkName, 175 resultsDirectory, 176 resultFile, 177 resultFormat, 178 projectName 179 ); 180 } 181 182 private static ResultFormatType parseResultFormat(String format) { 183 return switch (format.toUpperCase()) { 184 case "JSON" -> ResultFormatType.JSON; 185 case "CSV" -> ResultFormatType.CSV; 186 case "SCSV" -> ResultFormatType.SCSV; 187 case "LATEX" -> ResultFormatType.LATEX; 188 case "TEXT" -> ResultFormatType.TEXT; 189 default -> { 190 LOGGER.warn(UNKNOWN_RESULT_FORMAT, format); 191 yield ResultFormatType.JSON; 192 } 193 }; 194 } 195 } 196}