diff options
author | Øyvind Grønnesby <oyving@vespa.ai> | 2023-10-30 21:53:18 +0100 |
---|---|---|
committer | Øyvind Grønnesby <oyving@vespa.ai> | 2023-10-30 21:53:18 +0100 |
commit | 6866757fa3f88588cf0ffe29e6dd656bdf8ac0dc (patch) | |
tree | d9d5177efdf7bb6a3a7718e102b50a0d44709178 /controller-api | |
parent | 4bd554338d34e4c4884b7314ab7b06f5f061aa46 (diff) |
Allow for summarizing bills based on dimensions
Diffstat (limited to 'controller-api')
-rw-r--r-- | controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/Bill.java | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/Bill.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/Bill.java index e7959d2057a..45e643ca54c 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/Bill.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/Bill.java @@ -10,11 +10,18 @@ import com.yahoo.config.provision.zone.ZoneId; import java.math.BigDecimal; import java.time.LocalDate; import java.time.ZonedDateTime; +import java.util.Collection; +import java.util.EnumMap; +import java.util.EnumSet; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Optional; +import java.util.Set; +import java.util.TreeSet; import java.util.UUID; import java.util.function.Function; +import java.util.stream.Collectors; /** @@ -344,6 +351,14 @@ public class Bill { return Optional.ofNullable(exportedId); } + public boolean isAdditional() { + return cpuCost != null && diskCost != null && memoryCost != null && gpuCost != null; + } + + public boolean isResource() { + return ! isAdditional(); + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -384,4 +399,76 @@ public class Bill { } } + public enum ItemKeyType { + plan(LineItem::plan), + version(LineItem::getMajorVersion), + account(LineItem::getCloudAccount), + architecture(LineItem::getArchitecture); + + private final Function<LineItem, Object> extractor; + + ItemKeyType(Function<LineItem, Object> extractor) { + this.extractor = extractor; + } + + public Function<LineItem, Object> extractor() { + return extractor; + } + } + + public record ItemKey(EnumMap<ItemKeyType, Object> keys) {} + + public record ItemRequest(TreeSet<ItemKeyType> keyTypes) { + public static ItemRequest of(Collection<ItemKeyType> keyTypes) { + return new ItemRequest(new TreeSet<>(keyTypes)); + } + } + public record ItemSummary( + BigDecimal cpuUsage, + BigDecimal ramUsage, + BigDecimal diskUsage, + BigDecimal gpuUsage, + BigDecimal cpuCost, + BigDecimal ramCost, + BigDecimal diskCost, + BigDecimal gpuCost) { + + static ItemSummary from(List<LineItem> items) { + return new ItemSummary( + sum(items, LineItem::getCpuHours), + sum(items, LineItem::getMemoryHours), + sum(items, LineItem::getDiskHours), + sum(items, LineItem::getGpuHours), + sum(items, LineItem::getCpuCost), + sum(items, LineItem::getMemoryCost), + sum(items, LineItem::getDiskCost), + sum(items, LineItem::getGpuCost)); + } + + private static BigDecimal sum(List<LineItem> items, Function<LineItem, Optional<BigDecimal>> mapper) { + return items.stream().map(mapper).map(o -> o.orElse(BigDecimal.ZERO)).reduce(BigDecimal.ZERO, BigDecimal::add); + } + } + + public Map<ItemKey, ItemSummary> summarizeBy(ItemRequest request) { + var itemsByKey = this.lineItems.stream() + .filter(LineItem::isResource) + .collect( + Collectors.groupingBy( + (LineItem item) -> createKeyFromItem(request, item), + Collectors.toList())); + + return itemsByKey.entrySet().stream() + .map(item -> Map.entry(item.getKey(), ItemSummary.from(item.getValue()))) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } + + private static ItemKey createKeyFromItem(ItemRequest request, LineItem item) { + var key = new EnumMap<>(ItemKeyType.class); + for (var keyType : request.keyTypes()) { + key.put(keyType, keyType.extractor().apply(item)); + } + return new ItemKey(key); + } + } |