diff options
author | Øyvind Grønnesby <oyving@verizonmedia.com> | 2020-02-11 21:02:14 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-02-11 21:02:14 +0100 |
commit | 9b2d74a9f81fc973a858ff80a2f9b3cc568526b2 (patch) | |
tree | 006f4dfa65d505e4af7d9ddd6a05a70988a9d2f5 | |
parent | 0200e6c6c57c69f4a877d3f5eccb0b9eeb79f293 (diff) | |
parent | 7ee5738452cbae5413bfc6fb904290a0474dd0ae (diff) |
Merge pull request #12155 from vespa-engine/olaa/get-raw-snapshot-history
Get raw snapshot history for tenant
9 files changed, 112 insertions, 19 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/resource/MeteringClient.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/resource/MeteringClient.java index 3e06b24c6be..1047e1a02a4 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/resource/MeteringClient.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/resource/MeteringClient.java @@ -4,7 +4,9 @@ package com.yahoo.vespa.hosted.controller.api.integration.resource; import com.yahoo.config.provision.ApplicationName; import com.yahoo.config.provision.TenantName; +import java.time.YearMonth; import java.util.Collection; +import java.util.List; /** * Consumes and retrieves snapshots of resources allocated per application. @@ -15,6 +17,8 @@ public interface MeteringClient { void consume(Collection<ResourceSnapshot> resources); - MeteringInfo getResourceSnapshots(TenantName tenantName, ApplicationName applicationName); + MeteringData getMeteringData(TenantName tenantName, ApplicationName applicationName); + + List<ResourceSnapshot> getSnapshotHistoryForTenant(TenantName tenantName, YearMonth yearMonth); } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/resource/MeteringInfo.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/resource/MeteringData.java index d6cb8f7fe76..e9a6c81e636 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/resource/MeteringInfo.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/resource/MeteringData.java @@ -9,14 +9,14 @@ import java.util.Map; /** * @author olaa */ -public class MeteringInfo { +public class MeteringData { private final ResourceAllocation thisMonth; private final ResourceAllocation lastMonth; private final ResourceAllocation currentSnapshot; Map<ApplicationId, List<ResourceSnapshot>> snapshotHistory; - public MeteringInfo(ResourceAllocation thisMonth, ResourceAllocation lastMonth, ResourceAllocation currentSnapshot, Map<ApplicationId, List<ResourceSnapshot>> snapshotHistory) { + public MeteringData(ResourceAllocation thisMonth, ResourceAllocation lastMonth, ResourceAllocation currentSnapshot, Map<ApplicationId, List<ResourceSnapshot>> snapshotHistory) { this.thisMonth = thisMonth; this.lastMonth = lastMonth; this.currentSnapshot = currentSnapshot; diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/stubs/MockMeteringClient.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/stubs/MockMeteringClient.java index 45ead36f622..80caef1709d 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/stubs/MockMeteringClient.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/stubs/MockMeteringClient.java @@ -3,16 +3,19 @@ package com.yahoo.vespa.hosted.controller.api.integration.stubs; import com.yahoo.config.provision.ApplicationName; import com.yahoo.config.provision.TenantName; -import com.yahoo.vespa.hosted.controller.api.integration.resource.MeteringInfo; +import com.yahoo.vespa.hosted.controller.api.integration.resource.MeteringData; import com.yahoo.vespa.hosted.controller.api.integration.resource.ResourceAllocation; import com.yahoo.vespa.hosted.controller.api.integration.resource.ResourceSnapshot; import com.yahoo.vespa.hosted.controller.api.integration.resource.MeteringClient; +import java.time.YearMonth; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Optional; +import java.util.stream.Collectors; /** * @author olaa @@ -20,7 +23,7 @@ import java.util.Optional; public class MockMeteringClient implements MeteringClient { private Collection<ResourceSnapshot> resources = new ArrayList<>(); - private Optional<MeteringInfo> meteringInfo; + private Optional<MeteringData> meteringData; @Override public void consume(Collection<ResourceSnapshot> resources){ @@ -28,18 +31,25 @@ public class MockMeteringClient implements MeteringClient { } @Override - public MeteringInfo getResourceSnapshots(TenantName tenantName, ApplicationName applicationName) { - return meteringInfo.orElseGet(() -> { + public MeteringData getMeteringData(TenantName tenantName, ApplicationName applicationName) { + return meteringData.orElseGet(() -> { ResourceAllocation emptyAllocation = new ResourceAllocation(0, 0, 0); - return new MeteringInfo(emptyAllocation, emptyAllocation, emptyAllocation, Collections.emptyMap()); + return new MeteringData(emptyAllocation, emptyAllocation, emptyAllocation, Collections.emptyMap()); }); } + @Override + public List<ResourceSnapshot> getSnapshotHistoryForTenant(TenantName tenantName, YearMonth yearMonth) { + return new ArrayList<>(resources); + } + public Collection<ResourceSnapshot> consumedResources() { return this.resources; } - public void setMeteringInfo(MeteringInfo meteringInfo) { - this.meteringInfo = Optional.of(meteringInfo); + public void setMeteringData(MeteringData meteringData) { + this.meteringData = Optional.of(meteringData); + this.resources = meteringData.getSnapshotHistory().entrySet().stream().map(Map.Entry::getValue).flatMap(List::stream).collect(Collectors.toList()); + boolean a = false; } } 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 bf1b6c5ab84..f37304025ac 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 @@ -56,7 +56,7 @@ import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType; import com.yahoo.vespa.hosted.controller.api.integration.deployment.RunId; import com.yahoo.vespa.hosted.controller.api.integration.deployment.SourceRevision; import com.yahoo.vespa.hosted.controller.api.integration.resource.CostInfo; -import com.yahoo.vespa.hosted.controller.api.integration.resource.MeteringInfo; +import com.yahoo.vespa.hosted.controller.api.integration.resource.MeteringData; import com.yahoo.vespa.hosted.controller.api.integration.resource.ResourceAllocation; import com.yahoo.vespa.hosted.controller.api.integration.resource.ResourceSnapshot; import com.yahoo.vespa.hosted.controller.api.role.Role; @@ -1272,33 +1272,34 @@ public class ApplicationApiHandler extends LoggingRequestHandler { } private HttpResponse metering(String tenant, String application, HttpRequest request) { + Slime slime = new Slime(); Cursor root = slime.setObject(); - MeteringInfo meteringInfo = controller.serviceRegistry() + MeteringData meteringData = controller.serviceRegistry() .meteringService() - .getResourceSnapshots(TenantName.from(tenant), ApplicationName.from(application)); + .getMeteringData(TenantName.from(tenant), ApplicationName.from(application)); - ResourceAllocation currentSnapshot = meteringInfo.getCurrentSnapshot(); + 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 = meteringInfo.getThisMonth(); + 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 = meteringInfo.getLastMonth(); + 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 = meteringInfo.getSnapshotHistory(); + Map<ApplicationId, List<ResourceSnapshot>> history = meteringData.getSnapshotHistory(); Cursor details = root.setObject("details"); Cursor detailsCpu = details.setObject("cpu"); diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/controller/ControllerApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/controller/ControllerApiHandler.java index ad847621c3e..ea3559a92ae 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/controller/ControllerApiHandler.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/controller/ControllerApiHandler.java @@ -70,6 +70,7 @@ public class ControllerApiHandler extends AuditLoggingRequestHandler { if (path.matches("/controller/v1/auditlog/")) return new AuditLogResponse(controller.auditLogger().readLog()); if (path.matches("/controller/v1/maintenance/")) return new JobsResponse(maintenance.jobControl()); if (path.matches("/controller/v1/jobs/upgrader")) return new UpgraderResponse(maintenance.upgrader()); + if (path.matches("/controller/v1/metering/tenant/{tenant}/month/{month}")) return new MeteringResponse(controller.serviceRegistry().meteringService(), path.get("tenant"), path.get("month")); return notFound(path); } 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 new file mode 100644 index 00000000000..23e3195db01 --- /dev/null +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/controller/MeteringResponse.java @@ -0,0 +1,39 @@ +// Copyright 2020 Oath Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.controller.restapi.controller; + +import com.yahoo.config.provision.TenantName; +import com.yahoo.restapi.SlimeJsonResponse; +import com.yahoo.slime.Cursor; +import com.yahoo.slime.Slime; +import com.yahoo.vespa.hosted.controller.api.integration.resource.MeteringClient; +import com.yahoo.vespa.hosted.controller.api.integration.resource.ResourceSnapshot; + +import java.time.YearMonth; +import java.util.List; + +/** + * @author olaa + */ +public class MeteringResponse extends SlimeJsonResponse { + + public MeteringResponse(MeteringClient meteringClient, String tenantName, String month) { + super(toSlime(meteringClient, tenantName, month)); + } + + private static Slime toSlime(MeteringClient meteringClient, String tenantName, String month) { + Slime slime = new Slime(); + Cursor root = slime.setArray(); + List<ResourceSnapshot> snapshots = meteringClient.getSnapshotHistoryForTenant(TenantName.from(tenantName), YearMonth.parse(month)); + snapshots.forEach(snapshot -> { + Cursor object = root.addObject(); + 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()); + }); + return slime; + } + +} 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 0f846ab57e4..fb7d54759f8 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 @@ -40,7 +40,7 @@ import com.yahoo.vespa.hosted.controller.api.integration.organization.Contact; import com.yahoo.vespa.hosted.controller.api.integration.organization.IssueId; import com.yahoo.vespa.hosted.controller.api.integration.organization.User; import com.yahoo.vespa.hosted.controller.api.integration.resource.CostInfo; -import com.yahoo.vespa.hosted.controller.api.integration.resource.MeteringInfo; +import com.yahoo.vespa.hosted.controller.api.integration.resource.MeteringData; import com.yahoo.vespa.hosted.controller.api.integration.resource.MockTenantCost; import com.yahoo.vespa.hosted.controller.api.integration.resource.ResourceAllocation; import com.yahoo.vespa.hosted.controller.api.integration.resource.ResourceSnapshot; @@ -944,7 +944,7 @@ public class ApplicationApiTest extends ControllerContainerTest { new ResourceSnapshot(applicationId, 1, 2,3, Instant.ofEpochMilli(246), ZoneId.defaultId()), new ResourceSnapshot(applicationId, 1, 2,3, Instant.ofEpochMilli(492), ZoneId.defaultId()))); - mockMeteringClient.setMeteringInfo(new MeteringInfo(thisMonth, lastMonth, currentSnapshot, snapshotHistory)); + mockMeteringClient.setMeteringData(new MeteringData(thisMonth, lastMonth, currentSnapshot, snapshotHistory)); tester.assertResponse(request("/application/v4/tenant/doesnotexist/application/doesnotexist/metering", GET) .userIdentity(USER_ID) 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 b21c588235e..8029d650b75 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 @@ -2,8 +2,11 @@ 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.zone.ZoneId; import com.yahoo.container.jdisc.HttpRequest; import com.yahoo.test.ManualClock; +import com.yahoo.vespa.hosted.controller.api.integration.resource.ResourceSnapshot; import com.yahoo.vespa.hosted.controller.auditlog.AuditLogger; import com.yahoo.vespa.hosted.controller.restapi.ContainerTester; import com.yahoo.vespa.hosted.controller.restapi.ControllerContainerTest; @@ -15,6 +18,7 @@ import java.io.File; import java.nio.charset.StandardCharsets; import java.time.Duration; import java.time.Instant; +import java.util.List; import java.util.Set; import static org.junit.Assert.assertFalse; @@ -156,4 +160,20 @@ public class ControllerApiTest extends ControllerContainerTest { tester.assertResponse(authenticatedRequest("http://localhost:8080/controller/v1/auditlog/"), new File("auditlog.json")); } + @Test + public void testMeteringApi() { + ApplicationId applicationId = ApplicationId.from("tenant", "app", "instance"); + 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) + ); + tester.controller().serviceRegistry().meteringService().consume(snapshots); + tester.assertResponse( + operatorRequest("http://localhost:8080/controller/v1/metering/tenant/tenantName/month/2020-02", "", Request.Method.GET), + new File("metering.json") + ); + } + } 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 new file mode 100644 index 00000000000..b64e8f26a63 --- /dev/null +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/responses/metering.json @@ -0,0 +1,18 @@ +[ + { + "applicationId": "tenant.app.instance", + "timestamp": 123456789, + "zoneId": "prod.default", + "cpu": 12.0, + "memory": 48.0, + "disk": 1200.0 + }, + { + "applicationId": "tenant.app.instance", + "timestamp": 123456789, + "zoneId": "prod.default", + "cpu": 24.0, + "memory": 96.0, + "disk": 2400.0 + } +]
\ No newline at end of file |