diff options
author | Øyvind Grønnesby <oyving@yahooinc.com> | 2023-03-08 15:04:28 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-08 15:04:28 +0100 |
commit | 2134efb6eb0f3988571e773f5fe996ec3c3e47ab (patch) | |
tree | eea17153b99b95678d2b5224c77a4bc51412224b /controller-server/src/main/java/com/yahoo | |
parent | b180fdfea329bc7e6e09cbcd1fefe67dc2f22202 (diff) | |
parent | 3c325c2ee25bc1d39190dfe7ee5b43eadc6225c0 (diff) |
Merge pull request #26173 from vespa-engine/ogronnesby/billing-dimensions
New billing dimensions
Diffstat (limited to 'controller-server/src/main/java/com/yahoo')
4 files changed, 42 insertions, 29 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 d47b82a231f..26edd210075 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 @@ -120,7 +120,7 @@ public class ResourceMeterMaintainer extends ControllerMaintainer { Map<ZoneId, Double> deploymentCosts = snapshotsByInstance.getOrDefault(instanceName, List.of()).stream() .collect(Collectors.toUnmodifiableMap( ResourceSnapshot::getZoneId, - snapshot -> cost(snapshot.allocation(), systemName), + snapshot -> cost(snapshot.resources(), systemName), Double::sum)); locked = locked.with(instanceName, i -> i.withDeploymentCosts(deploymentCosts)); updateCostMetrics(tenantAndApplication.instance(instanceName), deploymentCosts); @@ -201,10 +201,11 @@ public class ResourceMeterMaintainer extends ControllerMaintainer { // Grouping by ApplicationId -> Architecture -> ResourceSnapshot .collect(Collectors.groupingBy(node -> node.owner().get(), - groupSnapshotsByArchitecture(zoneId))) + groupSnapshotsByArchitectureAndMajorVersion(zoneId))) .values() .stream() - .flatMap(list -> list.values().stream()) + .flatMap(byArch -> byArch.values().stream()) + .flatMap(byMajor -> byMajor.values().stream()) .toList(); } @@ -234,10 +235,14 @@ public class ResourceMeterMaintainer extends ControllerMaintainer { } private static double cost(ResourceAllocation allocation, SystemName systemName) { + var resources = new NodeResources(allocation.getCpuCores(), allocation.getMemoryGb(), allocation.getDiskGb(), 0); + return cost(resources, systemName); + } + + private static double cost(NodeResources resources, SystemName systemName) { // Divide cost by 3 in non-public zones to show approx. AWS equivalent cost double costDivisor = systemName.isPublic() ? 1.0 : 3.0; - double cost = new NodeResources(allocation.getCpuCores(), allocation.getMemoryGb(), allocation.getDiskGb(), 0).cost(); - return Math.round(cost * 100.0 / costDivisor) / 100.0; + return Math.round(resources.cost() * 100.0 / costDivisor) / 100.0; } private void updateMeteringMetrics(Collection<ResourceSnapshot> resourceSnapshots) { @@ -245,14 +250,14 @@ public class ResourceMeterMaintainer extends ControllerMaintainer { // total metered resource usage, for alerting on drastic changes metric.set(METERING_TOTAL_REPORTED, resourceSnapshots.stream() - .mapToDouble(r -> r.getCpuCores() + r.getMemoryGb() + r.getDiskGb()).sum(), + .mapToDouble(r -> r.resources().vcpu() + r.resources().memoryGb() + r.resources().diskGb()).sum(), metric.createContext(Collections.emptyMap())); resourceSnapshots.forEach(snapshot -> { 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); + metric.set("metering.vcpu", snapshot.resources().vcpu(), context); + metric.set("metering.memoryGB", snapshot.resources().memoryGb(), context); + metric.set("metering.diskGB", snapshot.resources().diskGb(), context); }); } @@ -276,23 +281,26 @@ public class ResourceMeterMaintainer extends ControllerMaintainer { "tenant", snapshot.getApplicationId().tenant().value(), "applicationId", snapshot.getApplicationId().toFullString(), "zoneId", snapshot.getZoneId().value(), - "architecture", snapshot.getArchitecture() + "architecture", snapshot.resources().architecture() )); } - private Collector<Node, ?, Map<NodeResources.Architecture, ResourceSnapshot>> groupSnapshotsByArchitecture(ZoneId zoneId) { - return Collectors.collectingAndThen( - Collectors.groupingBy(node -> node.resources().architecture()), - convertNodeListToResourceSnapshot(zoneId) - ); + private Collector<Node, ?, Map<NodeResources.Architecture, Map<Integer, ResourceSnapshot>>> groupSnapshotsByArchitectureAndMajorVersion(ZoneId zoneId) { + return Collectors.groupingBy( + (Node node) -> node.resources().architecture(), + Collectors.collectingAndThen( + Collectors.groupingBy( + (Node node) -> node.currentVersion().getMajor(), + Collectors.toList()), + 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)) - ); + private Function<Map<Integer, List<Node>>, Map<Integer, ResourceSnapshot>> convertNodeListToResourceSnapshot(ZoneId zoneId) { + return nodesByMajor -> { + return nodesByMajor.entrySet().stream() + .collect(Collectors.toMap( + entry -> entry.getKey(), + entry -> ResourceSnapshot.from(entry.getValue(), clock.instant(), zoneId))); + }; } } diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandler.java index 6e012ba619d..bc7dd4199c7 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandler.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandler.java @@ -35,8 +35,6 @@ import java.io.IOException; import java.math.BigDecimal; import java.security.Principal; import java.time.LocalDate; -import java.time.ZoneId; -import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.util.Comparator; @@ -44,7 +42,6 @@ import java.util.List; import java.util.Optional; import java.util.Set; import java.util.concurrent.Executor; -import java.util.stream.Collectors; /** * @author andreer @@ -421,6 +418,12 @@ public class BillingApiHandler extends ThreadedHttpRequestHandler { cursor.setString("zone", zoneId.value()) ); + lineItem.getArchitecture().ifPresent(architecture -> { + cursor.setString("architecture", architecture.name()); + }); + + cursor.setLong("majorVersion", lineItem.getMajorVersion()); + lineItem.getCpuHours().ifPresent(cpuHours -> cursor.setString("cpuHours", cpuHours.toString()) ); diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerV2.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerV2.java index 0ddaa409ef8..67dd172fd83 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerV2.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerV2.java @@ -311,6 +311,8 @@ public class BillingApiHandlerV2 extends RestApiRequestHandler<BillingApiHandler slime.setString("description", item.description()); slime.setString("amount",item.amount().toString()); toSlime(slime.setObject("plan"), planRegistry.plan(item.plan()).orElseThrow(() -> new RuntimeException("No such plan: '" + item.plan() + "'"))); + item.getArchitecture().ifPresent(arch -> slime.setString("architecture", arch.name())); + slime.setLong("majorVersion", item.getMajorVersion()); item.applicationId().ifPresent(appId -> { slime.setString("application", appId.application().value()); 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 17461aafd02..7df216d6c9c 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 @@ -29,10 +29,10 @@ public class MeteringResponse extends SlimeJsonResponse { object.setString("applicationId", snapshot.getApplicationId().toShortString()); object.setLong("timestamp", snapshot.getTimestamp().toEpochMilli()); object.setString("zoneId", snapshot.getZoneId().value()); - object.setDouble("cpu", snapshot.getCpuCores()); - object.setDouble("memory", snapshot.getMemoryGb()); - object.setDouble("disk", snapshot.getDiskGb()); - object.setString("architecture", snapshot.getArchitecture().name()); + object.setDouble("cpu", snapshot.resources().vcpu()); + object.setDouble("memory", snapshot.resources().memoryGb()); + object.setDouble("disk", snapshot.resources().diskGb()); + object.setString("architecture", snapshot.resources().architecture().name()); }); return slime; } |