Browse Source

[Profiling] Improve parameterized request test (#102972)

* [Profiling] Add co2/cost params to stacktrace request test

* Extract class GetStackTracesResponseBuilder.java

* Cover GetStackTracesResponseBuilder in tests

* Assert-test single response fields

---------

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
Tim Rühsen 1 year ago
parent
commit
d7c6c2253d

+ 155 - 0
x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/GetStackTracesResponseBuilder.java

@@ -0,0 +1,155 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+package org.elasticsearch.xpack.profiling;
+
+import java.time.Instant;
+import java.util.List;
+import java.util.Map;
+
+class GetStackTracesResponseBuilder {
+    private Map<String, StackTrace> stackTraces;
+    private Instant start;
+    private Instant end;
+    private int totalFrames;
+    private Map<String, StackFrame> stackFrames;
+    private Map<String, String> executables;
+    private Map<String, TraceEvent> stackTraceEvents;
+    private List<TransportGetStackTracesAction.HostEventCount> hostEventCounts;
+    private double samplingRate;
+    private long totalSamples;
+    private Double requestedDuration;
+    private final Double awsCostFactor;
+    private final Double customCO2PerKWH;
+    private final Double customDatacenterPUE;
+    private final Double customPerCoreWattX86;
+    private final Double customPerCoreWattARM64;
+    private final Double customCostPerCoreHour;
+
+    public void setStackTraces(Map<String, StackTrace> stackTraces) {
+        this.stackTraces = stackTraces;
+    }
+
+    public Instant getStart() {
+        return start;
+    }
+
+    public void setStart(Instant start) {
+        this.start = start;
+    }
+
+    public Instant getEnd() {
+        return end;
+    }
+
+    public void setEnd(Instant end) {
+        this.end = end;
+    }
+
+    public void setTotalFrames(int totalFrames) {
+        this.totalFrames = totalFrames;
+    }
+
+    public void setStackFrames(Map<String, StackFrame> stackFrames) {
+        this.stackFrames = stackFrames;
+    }
+
+    public void setExecutables(Map<String, String> executables) {
+        this.executables = executables;
+    }
+
+    public void setStackTraceEvents(Map<String, TraceEvent> stackTraceEvents) {
+        this.stackTraceEvents = stackTraceEvents;
+    }
+
+    public void setHostEventCounts(List<TransportGetStackTracesAction.HostEventCount> hostEventCounts) {
+        this.hostEventCounts = hostEventCounts;
+    }
+
+    public List<TransportGetStackTracesAction.HostEventCount> getHostEventCounts() {
+        return hostEventCounts;
+    }
+
+    public Map<String, TraceEvent> getStackTraceEvents() {
+        return stackTraceEvents;
+    }
+
+    public void setSamplingRate(double rate) {
+        this.samplingRate = rate;
+    }
+
+    public double getSamplingRate() {
+        return samplingRate;
+    }
+
+    public void setRequestedDuration(Double requestedDuration) {
+        this.requestedDuration = requestedDuration;
+    }
+
+    public double getRequestedDuration() {
+        if (requestedDuration != null) {
+            return requestedDuration;
+        }
+        // If "requested_duration" wasn't specified, we use the time range from the query response.
+        return end.getEpochSecond() - start.getEpochSecond();
+    }
+
+    public Double getAWSCostFactor() {
+        return awsCostFactor;
+    }
+
+    public Double getCustomCO2PerKWH() {
+        return customCO2PerKWH;
+    }
+
+    public Double getCustomDatacenterPUE() {
+        return customDatacenterPUE;
+    }
+
+    public Double getCustomPerCoreWattX86() {
+        return customPerCoreWattX86;
+    }
+
+    public Double getCustomPerCoreWattARM64() {
+        return customPerCoreWattARM64;
+    }
+
+    public Double getCustomCostPerCoreHour() {
+        return customCostPerCoreHour;
+    }
+
+    public void setTotalSamples(long totalSamples) {
+        this.totalSamples = totalSamples;
+    }
+
+    GetStackTracesResponseBuilder(GetStackTracesRequest request) {
+        this.requestedDuration = request.getRequestedDuration();
+        this.awsCostFactor = request.getAwsCostFactor();
+        this.customCO2PerKWH = request.getCustomCO2PerKWH();
+        this.customDatacenterPUE = request.getCustomDatacenterPUE();
+        this.customPerCoreWattX86 = request.getCustomPerCoreWattX86();
+        this.customPerCoreWattARM64 = request.getCustomPerCoreWattARM64();
+        this.customCostPerCoreHour = request.getCustomCostPerCoreHour();
+    }
+
+    public GetStackTracesResponse build() {
+        // Merge the TraceEvent data into the StackTraces.
+        if (stackTraces != null) {
+            for (Map.Entry<String, StackTrace> entry : stackTraces.entrySet()) {
+                String stacktraceID = entry.getKey();
+                TraceEvent event = stackTraceEvents.get(stacktraceID);
+                if (event != null) {
+                    StackTrace stackTrace = entry.getValue();
+                    stackTrace.count = event.count;
+                    stackTrace.annualCO2Tons = event.annualCO2Tons;
+                    stackTrace.annualCostsUSD = event.annualCostsUSD;
+                }
+            }
+        }
+        return new GetStackTracesResponse(stackTraces, stackFrames, executables, stackTraceEvents, totalFrames, samplingRate, totalSamples);
+    }
+}

+ 11 - 155
x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/TransportGetStackTracesAction.java

@@ -149,14 +149,7 @@ public class TransportGetStackTracesAction extends HandledTransportAction<GetSta
     @Override
     protected void doExecute(Task submitTask, GetStackTracesRequest request, ActionListener<GetStackTracesResponse> submitListener) {
         licenseChecker.requireSupportedLicense();
-        GetStackTracesResponseBuilder responseBuilder = new GetStackTracesResponseBuilder();
-        responseBuilder.setRequestedDuration(request.getRequestedDuration());
-        responseBuilder.setAwsCostFactor(request.getAwsCostFactor());
-        responseBuilder.setCustomCO2PerKWH(request.getCustomCO2PerKWH());
-        responseBuilder.setCustomDatacenterPUE(request.getCustomDatacenterPUE());
-        responseBuilder.setCustomPerCoreWattX86(request.getCustomPerCoreWattX86());
-        responseBuilder.setCustomPerCoreWattARM64(request.getCustomPerCoreWattARM64());
-        responseBuilder.setCustomCostPerCoreHour(request.getCustomCostPerCoreHour());
+        GetStackTracesResponseBuilder responseBuilder = new GetStackTracesResponseBuilder(request);
         Client client = new ParentTaskAssigningClient(this.nodeClient, transportService.getLocalNode(), submitTask);
         if (request.getIndices() == null) {
             searchProfilingEvents(submitTask, client, request, submitListener, responseBuilder);
@@ -413,8 +406,8 @@ public class TransportGetStackTracesAction extends HandledTransportAction<GetSta
         List<Index> indices = resolver.resolve(clusterState, "profiling-stacktraces", responseBuilder.getStart(), responseBuilder.getEnd());
 
         // Build a set of unique host IDs.
-        Set<String> uniqueHostIDs = new HashSet<>(responseBuilder.hostEventCounts.size());
-        for (HostEventCount hec : responseBuilder.hostEventCounts) {
+        Set<String> uniqueHostIDs = new HashSet<>(responseBuilder.getHostEventCounts().size());
+        for (HostEventCount hec : responseBuilder.getHostEventCounts()) {
             uniqueHostIDs.add(hec.hostID);
         }
 
@@ -557,21 +550,21 @@ public class TransportGetStackTracesAction extends HandledTransportAction<GetSta
                 instanceTypeService,
                 hostMetadata,
                 responseBuilder.getRequestedDuration(),
-                responseBuilder.customCO2PerKWH,
-                responseBuilder.customDatacenterPUE,
-                responseBuilder.customPerCoreWattX86,
-                responseBuilder.customPerCoreWattARM64
+                responseBuilder.getCustomCO2PerKWH(),
+                responseBuilder.getCustomDatacenterPUE(),
+                responseBuilder.getCustomPerCoreWattX86(),
+                responseBuilder.getCustomPerCoreWattARM64()
             );
             CostCalculator costCalculator = new CostCalculator(
                 instanceTypeService,
                 hostMetadata,
                 responseBuilder.getRequestedDuration(),
-                responseBuilder.awsCostFactor,
-                responseBuilder.customCostPerCoreHour
+                responseBuilder.getAWSCostFactor(),
+                responseBuilder.getCustomCostPerCoreHour()
             );
-            Map<String, TraceEvent> events = responseBuilder.stackTraceEvents;
+            Map<String, TraceEvent> events = responseBuilder.getStackTraceEvents();
             List<String> missingStackTraces = new ArrayList<>();
-            for (HostEventCount hec : responseBuilder.hostEventCounts) {
+            for (HostEventCount hec : responseBuilder.getHostEventCounts()) {
                 TraceEvent event = events.get(hec.stacktraceID);
                 if (event == null) {
                     // If this happens, hostEventsCounts and events are out of sync, which indicates a bug.
@@ -768,142 +761,5 @@ public class TransportGetStackTracesAction extends HandledTransportAction<GetSta
         }
     }
 
-    private static class GetStackTracesResponseBuilder {
-        private Map<String, StackTrace> stackTraces;
-        private Instant start;
-        private Instant end;
-        private int totalFrames;
-        private Map<String, StackFrame> stackFrames;
-        private Map<String, String> executables;
-        private Map<String, TraceEvent> stackTraceEvents;
-        private List<HostEventCount> hostEventCounts;
-        private double samplingRate;
-        private long totalSamples;
-        private Double requestedDuration;
-        private Double awsCostFactor;
-        private Double customCO2PerKWH;
-        private Double customDatacenterPUE;
-        private Double customPerCoreWattX86;
-        private Double customPerCoreWattARM64;
-        private Double customCostPerCoreHour;
-
-        public void setStackTraces(Map<String, StackTrace> stackTraces) {
-            this.stackTraces = stackTraces;
-        }
-
-        public Instant getStart() {
-            return start;
-        }
-
-        public void setStart(Instant start) {
-            this.start = start;
-        }
-
-        public Instant getEnd() {
-            return end;
-        }
-
-        public void setEnd(Instant end) {
-            this.end = end;
-        }
-
-        public void setTotalFrames(int totalFrames) {
-            this.totalFrames = totalFrames;
-        }
-
-        public void setStackFrames(Map<String, StackFrame> stackFrames) {
-            this.stackFrames = stackFrames;
-        }
-
-        public void setExecutables(Map<String, String> executables) {
-            this.executables = executables;
-        }
-
-        public void setStackTraceEvents(Map<String, TraceEvent> stackTraceEvents) {
-            this.stackTraceEvents = stackTraceEvents;
-        }
-
-        public void setHostEventCounts(List<HostEventCount> hostEventCounts) {
-            this.hostEventCounts = hostEventCounts;
-        }
-
-        public Map<String, TraceEvent> getStackTraceEvents() {
-            return stackTraceEvents;
-        }
-
-        public void setSamplingRate(double rate) {
-            this.samplingRate = rate;
-        }
-
-        public double getSamplingRate() {
-            return samplingRate;
-        }
-
-        public void setRequestedDuration(Double requestedDuration) {
-            this.requestedDuration = requestedDuration;
-        }
-
-        public double getRequestedDuration() {
-            if (requestedDuration != null) {
-                return requestedDuration;
-            }
-            // If "requested_duration" wasn't specified, we use the time range from the query response.
-            return end.getEpochSecond() - start.getEpochSecond();
-        }
-
-        public void setAwsCostFactor(Double awsCostFactor) {
-            this.awsCostFactor = awsCostFactor;
-        }
-
-        public void setCustomCO2PerKWH(Double customCO2PerKWH) {
-            this.customCO2PerKWH = customCO2PerKWH;
-        }
-
-        public void setCustomDatacenterPUE(Double customDatacenterPUE) {
-            this.customDatacenterPUE = customDatacenterPUE;
-        }
-
-        public void setCustomPerCoreWattX86(Double customPerCoreWattX86) {
-            this.customPerCoreWattX86 = customPerCoreWattX86;
-        }
-
-        public void setCustomPerCoreWattARM64(Double customPerCoreWattARM64) {
-            this.customPerCoreWattARM64 = customPerCoreWattARM64;
-        }
-
-        public void setCustomCostPerCoreHour(Double customCostPerCoreHour) {
-            this.customCostPerCoreHour = customCostPerCoreHour;
-        }
-
-        public void setTotalSamples(long totalSamples) {
-            this.totalSamples = totalSamples;
-        }
-
-        public GetStackTracesResponse build() {
-            // Merge the TraceEvent data into the StackTraces.
-            if (stackTraces != null) {
-                for (Map.Entry<String, StackTrace> entry : stackTraces.entrySet()) {
-                    String stacktraceID = entry.getKey();
-                    TraceEvent event = stackTraceEvents.get(stacktraceID);
-                    if (event != null) {
-                        StackTrace stackTrace = entry.getValue();
-                        stackTrace.count = event.count;
-                        stackTrace.annualCO2Tons = event.annualCO2Tons;
-                        stackTrace.annualCostsUSD = event.annualCostsUSD;
-                    }
-                }
-            }
-            return new GetStackTracesResponse(
-                stackTraces,
-                stackFrames,
-                executables,
-                stackTraceEvents,
-                totalFrames,
-                samplingRate,
-                totalSamples
-            );
-        }
-    }
-
     record HostEventCount(String hostID, String stacktraceID, int count) {}
 }

+ 29 - 9
x-pack/plugin/profiling/src/test/java/org/elasticsearch/xpack/profiling/RestGetStackTracesActionTests.java

@@ -66,17 +66,31 @@ public class RestGetStackTracesActionTests extends RestActionTestCase {
             assertThat(request, instanceOf(GetStackTracesRequest.class));
             GetStackTracesRequest getStackTracesRequest = (GetStackTracesRequest) request;
             assertThat(getStackTracesRequest.getSampleSize(), is(10_000));
+            assertThat(getStackTracesRequest.getRequestedDuration(), is(3_600.0d));
+            assertThat(getStackTracesRequest.getAwsCostFactor(), is(1.0d));
+            assertThat(getStackTracesRequest.getCustomCO2PerKWH(), is(0.005d));
+            assertThat(getStackTracesRequest.getCustomDatacenterPUE(), is(1.5d));
+            assertThat(getStackTracesRequest.getCustomPerCoreWattX86(), is(7.5d));
+            assertThat(getStackTracesRequest.getCustomPerCoreWattARM64(), is(2.0d));
+            assertThat(getStackTracesRequest.getCustomCostPerCoreHour(), is(0.083d));
             assertThat(getStackTracesRequest.getQuery(), notNullValue(QueryBuilder.class));
             executeCalled.set(true);
-            return new GetStackTracesResponse(
-                Collections.emptyMap(),
-                Collections.emptyMap(),
-                Collections.emptyMap(),
-                Collections.emptyMap(),
-                0,
-                0.0d,
-                0L
-            );
+
+            GetStackTracesResponseBuilder responseBuilder = new GetStackTracesResponseBuilder(getStackTracesRequest);
+            responseBuilder.setSamplingRate(0.04d);
+            responseBuilder.setTotalFrames(523);
+            responseBuilder.setTotalSamples(3L);
+
+            GetStackTracesResponse response = responseBuilder.build();
+            assertNull(response.getStackTraces());
+            assertNull(response.getStackFrames());
+            assertNull(response.getExecutables());
+            assertNull(response.getStackTraceEvents());
+            assertEquals(response.getSamplingRate(), 0.04d, 0.0001d);
+            assertEquals(response.getTotalFrames(), 523);
+            assertEquals(response.getTotalSamples(), 3L);
+
+            return response;
         });
         RestRequest request = new FakeRestRequest.Builder(xContentRegistry()).withMethod(RestRequest.Method.POST)
             .withPath("/_profiling/stacktraces")
@@ -84,6 +98,12 @@ public class RestGetStackTracesActionTests extends RestActionTestCase {
                             {
                               "sample_size": 10000,
                               "requested_duration": 3600,
+                              "aws_cost_factor": 1.0,
+                              "co2_per_kwh": 0.005,
+                              "datacenter_pue": 1.5,
+                              "per_core_watt_x86": 7.5,
+                              "per_core_watt_arm64": 2.0,
+                              "cost_per_core_hour": 0.083,
                               "query": {
                                 "bool": {
                                   "filter": [