summaryrefslogtreecommitdiffstats
path: root/controller-server
diff options
context:
space:
mode:
authorØyvind Grønnesby <oyving@yahooinc.com>2022-04-06 09:02:51 +0200
committerGitHub <noreply@github.com>2022-04-06 09:02:51 +0200
commitf70dd482c7f9dcafefb33cfb5d0de80153bcb9d2 (patch)
tree3993731a87689037f72ae961a83d59b8975adbc3 /controller-server
parent4dbf00faa83362bfe0f25ef1f2d689a4d58b05ab (diff)
parent51a4c78804b8d8f5bac4c4116a4f34f4375bcffa (diff)
Merge pull request #21784 from vespa-engine/olaa/architecture-metering
Include architecture in metering
Diffstat (limited to 'controller-server')
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ResourceMeterMaintainer.java45
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/metric/CostCalculator.java2
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java63
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/controller/MeteringResponse.java1
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/CostReportMaintainerTest.java3
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ResourceMeterMaintainerTest.java12
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java22
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/ControllerApiTest.java5
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/responses/metering.json6
9 files changed, 54 insertions, 105 deletions
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ResourceMeterMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ResourceMeterMaintainer.java
index acaf35133d7..d4905f7e20a 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ResourceMeterMaintainer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/ResourceMeterMaintainer.java
@@ -33,7 +33,9 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeoutException;
+import java.util.function.Function;
import java.util.logging.Level;
+import java.util.stream.Collector;
import java.util.stream.Collectors;
/**
@@ -150,14 +152,14 @@ public class ResourceMeterMaintainer extends ControllerMaintainer {
.filter(this::unlessNodeOwnerIsSystemApplication)
.filter(this::isNodeStateMeterable)
.filter(this::isClusterTypeMeterable)
+ // Grouping by ApplicationId -> Architecture -> ResourceSnapshot
.collect(Collectors.groupingBy(node ->
- node.owner().get(),
- Collectors.collectingAndThen(Collectors.toList(),
- nodeList -> ResourceSnapshot.from(
- nodeList,
- clock.instant(),
- zoneId))
- )).values();
+ node.owner().get(),
+ groupSnapshotsByArchitecture(zoneId)))
+ .values()
+ .stream()
+ .flatMap(list -> list.values().stream())
+ .collect(Collectors.toList());
}
private boolean unlessNodeOwnerIsSystemApplication(Node node) {
@@ -182,7 +184,7 @@ public class ResourceMeterMaintainer extends ControllerMaintainer {
public static double cost(ClusterResources clusterResources, SystemName systemName) {
NodeResources nr = clusterResources.nodeResources();
- return cost(new ResourceAllocation(nr.vcpu(), nr.memoryGb(), nr.diskGb()).multiply(clusterResources.nodes()), systemName);
+ return cost(new ResourceAllocation(nr.vcpu(), nr.memoryGb(), nr.diskGb(), nr.architecture()).multiply(clusterResources.nodes()), systemName);
}
private static double cost(ResourceAllocation allocation, SystemName systemName) {
@@ -201,7 +203,7 @@ public class ResourceMeterMaintainer extends ControllerMaintainer {
metric.createContext(Collections.emptyMap()));
resourceSnapshots.forEach(snapshot -> {
- var context = getMetricContext(snapshot.getApplicationId(), snapshot.getZoneId());
+ var context = getMetricContext(snapshot);
metric.set("metering.vcpu", snapshot.getCpuCores(), context);
metric.set("metering.memoryGB", snapshot.getMemoryGb(), context);
metric.set("metering.diskGB", snapshot.getDiskGb(), context);
@@ -222,4 +224,29 @@ public class ResourceMeterMaintainer extends ControllerMaintainer {
"zoneId", zoneId.value()
));
}
+
+ private Metric.Context getMetricContext(ResourceSnapshot snapshot) {
+ return metric.createContext(Map.of(
+ "tenant", snapshot.getApplicationId().tenant().value(),
+ "applicationId", snapshot.getApplicationId().toFullString(),
+ "zoneId", snapshot.getZoneId().value(),
+ "architecture", snapshot.getArchitecture()
+ ));
+ }
+
+ private Collector<Node, ?, Map<NodeResources.Architecture, ResourceSnapshot>> groupSnapshotsByArchitecture(ZoneId zoneId) {
+ return Collectors.collectingAndThen(
+ Collectors.groupingBy(node -> node.resources().architecture()),
+ convertNodeListToResourceSnapshot(zoneId)
+ );
+ }
+
+ private Function<Map<NodeResources.Architecture, List<Node>>, Map<NodeResources.Architecture, ResourceSnapshot>> convertNodeListToResourceSnapshot(ZoneId zoneId) {
+ return nodeMap -> nodeMap.entrySet()
+ .stream()
+ .collect(Collectors.toMap(
+ Map.Entry::getKey,
+ entry -> ResourceSnapshot.from(entry.getValue(), clock.instant(), zoneId))
+ );
+ }
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/metric/CostCalculator.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/metric/CostCalculator.java
index 089767dc586..b36b2b9cad8 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/metric/CostCalculator.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/metric/CostCalculator.java
@@ -57,7 +57,7 @@ public class CostCalculator {
Property property = propertyByTenantName.get(node.owner().get().tenant());
if (property == null) continue;
var allocation = allocationByProperty.getOrDefault(property, ResourceAllocation.ZERO);
- var nodeAllocation = new ResourceAllocation(node.resources().vcpu(), node.resources().memoryGb(), node.resources().diskGb());
+ var nodeAllocation = new ResourceAllocation(node.resources().vcpu(), node.resources().memoryGb(), node.resources().diskGb(), node.resources().architecture());
allocationByProperty.put(property, allocation.plus(nodeAllocation));
totalAllocation = totalAllocation.plus(nodeAllocation);
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
index d9a38a5b578..9089bb27035 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
@@ -255,7 +255,6 @@ public class ApplicationApiHandler extends AuditLoggingRequestHandler {
if (path.matches("/application/v4/tenant/{tenant}/application/{application}/diff/{number}")) return applicationPackageDiff(path.get("tenant"), path.get("application"), path.get("number"));
if (path.matches("/application/v4/tenant/{tenant}/application/{application}/deploying")) return deploying(path.get("tenant"), path.get("application"), "default", request);
if (path.matches("/application/v4/tenant/{tenant}/application/{application}/deploying/pin")) return deploying(path.get("tenant"), path.get("application"), "default", request);
- if (path.matches("/application/v4/tenant/{tenant}/application/{application}/metering")) return metering(path.get("tenant"), path.get("application"), request);
if (path.matches("/application/v4/tenant/{tenant}/application/{application}/instance")) return applications(path.get("tenant"), Optional.of(path.get("application")), request);
if (path.matches("/application/v4/tenant/{tenant}/application/{application}/instance/{instance}")) return instance(path.get("tenant"), path.get("application"), path.get("instance"), request);
if (path.matches("/application/v4/tenant/{tenant}/application/{application}/instance/{instance}/deploying")) return deploying(path.get("tenant"), path.get("application"), path.get("instance"), request);
@@ -1762,68 +1761,6 @@ public class ApplicationApiHandler extends AuditLoggingRequestHandler {
return new SlimeJsonResponse(slime);
}
- private HttpResponse metering(String tenant, String application, HttpRequest request) {
-
- Slime slime = new Slime();
- Cursor root = slime.setObject();
-
- MeteringData meteringData = controller.serviceRegistry()
- .meteringService()
- .getMeteringData(TenantName.from(tenant), ApplicationName.from(application));
-
- ResourceAllocation currentSnapshot = meteringData.getCurrentSnapshot();
- Cursor currentRate = root.setObject("currentrate");
- currentRate.setDouble("cpu", currentSnapshot.getCpuCores());
- currentRate.setDouble("mem", currentSnapshot.getMemoryGb());
- currentRate.setDouble("disk", currentSnapshot.getDiskGb());
-
- ResourceAllocation thisMonth = meteringData.getThisMonth();
- Cursor thismonth = root.setObject("thismonth");
- thismonth.setDouble("cpu", thisMonth.getCpuCores());
- thismonth.setDouble("mem", thisMonth.getMemoryGb());
- thismonth.setDouble("disk", thisMonth.getDiskGb());
-
- ResourceAllocation lastMonth = meteringData.getLastMonth();
- Cursor lastmonth = root.setObject("lastmonth");
- lastmonth.setDouble("cpu", lastMonth.getCpuCores());
- lastmonth.setDouble("mem", lastMonth.getMemoryGb());
- lastmonth.setDouble("disk", lastMonth.getDiskGb());
-
-
- Map<ApplicationId, List<ResourceSnapshot>> history = meteringData.getSnapshotHistory();
- Cursor details = root.setObject("details");
-
- Cursor detailsCpu = details.setObject("cpu");
- Cursor detailsMem = details.setObject("mem");
- Cursor detailsDisk = details.setObject("disk");
-
- history.forEach((applicationId, resources) -> {
- String instanceName = applicationId.instance().value();
- Cursor detailsCpuApp = detailsCpu.setObject(instanceName);
- Cursor detailsMemApp = detailsMem.setObject(instanceName);
- Cursor detailsDiskApp = detailsDisk.setObject(instanceName);
- Cursor detailsCpuData = detailsCpuApp.setArray("data");
- Cursor detailsMemData = detailsMemApp.setArray("data");
- Cursor detailsDiskData = detailsDiskApp.setArray("data");
-
- resources.forEach(resourceSnapshot -> {
- Cursor cpu = detailsCpuData.addObject();
- cpu.setLong("unixms", resourceSnapshot.getTimestamp().toEpochMilli());
- cpu.setDouble("value", resourceSnapshot.getCpuCores());
-
- Cursor mem = detailsMemData.addObject();
- mem.setLong("unixms", resourceSnapshot.getTimestamp().toEpochMilli());
- mem.setDouble("value", resourceSnapshot.getMemoryGb());
-
- Cursor disk = detailsDiskData.addObject();
- disk.setLong("unixms", resourceSnapshot.getTimestamp().toEpochMilli());
- disk.setDouble("value", resourceSnapshot.getDiskGb());
- });
- });
-
- return new SlimeJsonResponse(slime);
- }
-
private HttpResponse deploying(String tenantName, String applicationName, String instanceName, HttpRequest request) {
Instance instance = controller.applications().requireInstance(ApplicationId.from(tenantName, applicationName, instanceName));
Slime slime = new Slime();
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/controller/MeteringResponse.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/controller/MeteringResponse.java
index 850a9ef6107..33cd4948a7e 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/controller/MeteringResponse.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/controller/MeteringResponse.java
@@ -32,6 +32,7 @@ public class MeteringResponse extends SlimeJsonResponse {
object.setDouble("cpu", snapshot.getCpuCores());
object.setDouble("memory", snapshot.getMemoryGb());
object.setDouble("disk", snapshot.getDiskGb());
+ object.setString("architecture", snapshot.getArchitecture().name());
});
return slime;
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/CostReportMaintainerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/CostReportMaintainerTest.java
index 80ee0988658..10193b48837 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/CostReportMaintainerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/CostReportMaintainerTest.java
@@ -1,6 +1,7 @@
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.maintenance;
+import com.yahoo.config.provision.NodeResources;
import com.yahoo.vespa.hosted.controller.ControllerTester;
import com.yahoo.vespa.hosted.controller.api.identifiers.Property;
import com.yahoo.vespa.hosted.controller.api.integration.resource.ResourceAllocation;
@@ -38,7 +39,7 @@ public class CostReportMaintainerTest {
"1970-01-01,Property3,128.0,96.0,2000.0,0.3333333333333333\n" +
"1970-01-01,Property2,160.0,96.0,2000.0,0.3611111111111111",
csv),
- Map.of(new Property("Property3"), new ResourceAllocation(256, 192, 4000))
+ Map.of(new Property("Property3"), new ResourceAllocation(256, 192, 4000, NodeResources.Architecture.getDefault()))
);
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ResourceMeterMaintainerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ResourceMeterMaintainerTest.java
index 4acc9f91e79..6109890bae3 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ResourceMeterMaintainerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/ResourceMeterMaintainerTest.java
@@ -58,18 +58,18 @@ public class ResourceMeterMaintainerTest {
.collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().cost().getAsDouble())));
List<ResourceSnapshot> resourceSnapshots = List.of(
- new ResourceSnapshot(app1, 12, 34, 56, Instant.EPOCH, z1),
- new ResourceSnapshot(app1, 23, 45, 67, Instant.EPOCH, z2),
- new ResourceSnapshot(app2, 34, 56, 78, Instant.EPOCH, z1));
+ new ResourceSnapshot(app1, 12, 34, 56, NodeResources.Architecture.getDefault(), Instant.EPOCH, z1),
+ new ResourceSnapshot(app1, 23, 45, 67, NodeResources.Architecture.getDefault(), Instant.EPOCH, z2),
+ new ResourceSnapshot(app2, 34, 56, 78, NodeResources.Architecture.getDefault(), Instant.EPOCH, z1));
maintainer.updateDeploymentCost(resourceSnapshots);
assertCost.accept(app1, Map.of(z1, 1.40, z2, 2.50));
assertCost.accept(app2, Map.of(z1, 3.59));
// Remove a region from app1 and add region to app2
resourceSnapshots = List.of(
- new ResourceSnapshot(app1, 23, 45, 67, Instant.EPOCH, z2),
- new ResourceSnapshot(app2, 34, 56, 78, Instant.EPOCH, z1),
- new ResourceSnapshot(app2, 45, 67, 89, Instant.EPOCH, z2));
+ new ResourceSnapshot(app1, 23, 45, 67, NodeResources.Architecture.getDefault(), Instant.EPOCH, z2),
+ new ResourceSnapshot(app2, 34, 56, 78, NodeResources.Architecture.getDefault(), Instant.EPOCH, z1),
+ new ResourceSnapshot(app2, 45, 67, 89, NodeResources.Architecture.getDefault(), Instant.EPOCH, z2));
maintainer.updateDeploymentCost(resourceSnapshots);
assertCost.accept(app1, Map.of(z2, 2.50));
assertCost.accept(app2, Map.of(z1, 3.59, z2, 4.68));
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java
index f94f87b0f46..cc162548f33 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiTest.java
@@ -11,6 +11,7 @@ import com.yahoo.config.provision.ApplicationName;
import com.yahoo.config.provision.AthenzService;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.InstanceName;
+import com.yahoo.config.provision.NodeResources;
import com.yahoo.config.provision.RegionName;
import com.yahoo.config.provision.TenantName;
import com.yahoo.config.provision.zone.RoutingMethod;
@@ -1069,27 +1070,6 @@ public class ApplicationApiTest extends ControllerContainerTest {
new File("deploy-result.json"));
}
- @Test
- public void testMeteringResponses() {
- MockMeteringClient mockMeteringClient = tester.serviceRegistry().meteringService();
-
- // Mock response for MeteringClient
- ResourceAllocation currentSnapshot = new ResourceAllocation(1, 2, 3);
- ResourceAllocation thisMonth = new ResourceAllocation(12, 24, 1000);
- ResourceAllocation lastMonth = new ResourceAllocation(24, 48, 2000);
- ApplicationId applicationId = ApplicationId.from("doesnotexist", "doesnotexist", "default");
- Map<ApplicationId, List<ResourceSnapshot>> snapshotHistory = Map.of(applicationId, List.of(
- new ResourceSnapshot(applicationId, 1, 2,3, Instant.ofEpochMilli(123), ZoneId.defaultId()),
- new ResourceSnapshot(applicationId, 1, 2,3, Instant.ofEpochMilli(246), ZoneId.defaultId()),
- new ResourceSnapshot(applicationId, 1, 2,3, Instant.ofEpochMilli(492), ZoneId.defaultId())));
-
- mockMeteringClient.setMeteringData(new MeteringData(thisMonth, lastMonth, currentSnapshot, snapshotHistory));
-
- tester.assertResponse(request("/application/v4/tenant/doesnotexist/application/doesnotexist/metering", GET)
- .userIdentity(USER_ID)
- .oAuthCredentials(OKTA_CREDENTIALS),
- new File("instance1-metering.json"));
- }
@Test
public void testRemovingAllDeployments() {
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/ControllerApiTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/ControllerApiTest.java
index 7bc01de2053..8a6244e19a0 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/ControllerApiTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/ControllerApiTest.java
@@ -3,6 +3,7 @@ package com.yahoo.vespa.hosted.controller.restapi.controller;
import com.yahoo.application.container.handler.Request;
import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.config.provision.NodeResources;
import com.yahoo.config.provision.zone.ZoneId;
import com.yahoo.container.jdisc.HttpRequest;
import com.yahoo.test.ManualClock;
@@ -158,8 +159,8 @@ public class ControllerApiTest extends ControllerContainerTest {
Instant timestamp = Instant.ofEpochMilli(123456789);
ZoneId zoneId = ZoneId.defaultId();
List<ResourceSnapshot> snapshots = List.of(
- new ResourceSnapshot(applicationId, 12,48,1200, timestamp, zoneId),
- new ResourceSnapshot(applicationId, 24, 96,2400, timestamp, zoneId)
+ new ResourceSnapshot(applicationId, 12,48,1200, NodeResources.Architecture.arm64, timestamp, zoneId),
+ new ResourceSnapshot(applicationId, 24, 96,2400, NodeResources.Architecture.x86_64, timestamp, zoneId)
);
tester.controller().serviceRegistry().meteringService().consume(snapshots);
tester.assertResponse(
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/responses/metering.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/responses/metering.json
index b64e8f26a63..1008ada6def 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/responses/metering.json
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/responses/metering.json
@@ -5,7 +5,8 @@
"zoneId": "prod.default",
"cpu": 12.0,
"memory": 48.0,
- "disk": 1200.0
+ "disk": 1200.0,
+ "architecture":"arm64"
},
{
"applicationId": "tenant.app.instance",
@@ -13,6 +14,7 @@
"zoneId": "prod.default",
"cpu": 24.0,
"memory": 96.0,
- "disk": 2400.0
+ "disk": 2400.0,
+ "architecture":"x86_64"
}
] \ No newline at end of file