Skip to content

Commit

Permalink
Merge pull request #25 from nais/rework_usage_trend
Browse files Browse the repository at this point in the history
Utilization: When fetching specific data for team, group rows usable for
  • Loading branch information
christeredvartsen authored Apr 29, 2024
2 parents f79a1ae + 8339fcc commit 1c675d5
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 42 deletions.
14 changes: 7 additions & 7 deletions internal/database/gensql/mock_querier.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion internal/database/gensql/querier.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

44 changes: 32 additions & 12 deletions internal/database/gensql/resourceusage.sql.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 7 additions & 7 deletions internal/database/mock_database.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 5 additions & 4 deletions internal/database/queries/resourceusage.sql
Original file line number Diff line number Diff line change
Expand Up @@ -95,20 +95,21 @@ WHERE

-- SpecificResourceUtilizationForTeam will return resource utilization for a team at a specific timestamp. Applications
-- with a usage greater than request will be ignored.
-- name: SpecificResourceUtilizationForTeam :one
-- name: SpecificResourceUtilizationForTeam :many
SELECT
SUM(usage)::double precision AS usage,
SUM(request)::double precision AS request,
timestamp
timestamp,
request > usage as usable_for_cost
FROM
resource_utilization_metrics
WHERE
team_slug = @team_slug
AND resource_type = @resource_type
AND timestamp = @timestamp
AND request > usage
GROUP BY
timestamp;
timestamp, usable_for_cost
ORDER BY usable_for_cost DESC;

-- AverageResourceUtilizationForTeam will return the average resource utilization for a team for a week.
-- name: AverageResourceUtilizationForTeam :one
Expand Down
4 changes: 2 additions & 2 deletions internal/database/resource_utilization.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type ResourceUtilizationRepo interface {
ResourceUtilizationRefresh(ctx context.Context) error
ResourceUtilizationUpsert(ctx context.Context, arg []gensql.ResourceUtilizationUpsertParams) *gensql.ResourceUtilizationUpsertBatchResults
SpecificResourceUtilizationForApp(ctx context.Context, environment string, teamSlug slug.Slug, app string, resourceType gensql.ResourceType, timestamp pgtype.Timestamptz) (*gensql.SpecificResourceUtilizationForAppRow, error)
SpecificResourceUtilizationForTeam(ctx context.Context, teamSlug slug.Slug, resourceType gensql.ResourceType, timestamp pgtype.Timestamptz) (*gensql.SpecificResourceUtilizationForTeamRow, error)
SpecificResourceUtilizationForTeam(ctx context.Context, teamSlug slug.Slug, resourceType gensql.ResourceType, timestamp pgtype.Timestamptz) ([]*gensql.SpecificResourceUtilizationForTeamRow, error)
}

var _ ResourceUtilizationRepo = (*database)(nil)
Expand Down Expand Up @@ -95,7 +95,7 @@ func (d *database) SpecificResourceUtilizationForApp(ctx context.Context, enviro
})
}

func (d *database) SpecificResourceUtilizationForTeam(ctx context.Context, teamSlug slug.Slug, resourceType gensql.ResourceType, timestamp pgtype.Timestamptz) (*gensql.SpecificResourceUtilizationForTeamRow, error) {
func (d *database) SpecificResourceUtilizationForTeam(ctx context.Context, teamSlug slug.Slug, resourceType gensql.ResourceType, timestamp pgtype.Timestamptz) ([]*gensql.SpecificResourceUtilizationForTeamRow, error) {
return d.querier.SpecificResourceUtilizationForTeam(ctx, gensql.SpecificResourceUtilizationForTeamParams{
TeamSlug: teamSlug,
ResourceType: resourceType,
Expand Down
50 changes: 41 additions & 9 deletions internal/resourceusage/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,8 @@ func (c *client) CurrentResourceUtilizationForApp(ctx context.Context, env strin

return &model.CurrentResourceUtilization{
Timestamp: timeRange.To.Time,
CPU: resourceUtilization(model.ResourceTypeCPU, cpu.Timestamp.Time.UTC(), cpu.Request, cpu.Usage),
Memory: resourceUtilization(model.ResourceTypeMemory, memory.Timestamp.Time.UTC(), memory.Request, memory.Usage),
CPU: resourceUtilization(model.ResourceTypeCPU, cpu.Timestamp.Time.UTC(), cpu.Request, cpu.Usage, cpu.Request, cpu.Usage),
Memory: resourceUtilization(model.ResourceTypeMemory, memory.Timestamp.Time.UTC(), memory.Request, memory.Usage, memory.Request, memory.Usage),
}, nil
}

Expand Down Expand Up @@ -201,10 +201,13 @@ func (c *client) CurrentResourceUtilizationForTeam(ctx context.Context, team slu
return nil, fmt.Errorf("fetching current memory: %w", err)
}

sMem := joinSpecificRows(currentMemory)
sCpu := joinSpecificRows(currentCpu)

return &model.CurrentResourceUtilization{
Timestamp: timeRange.To.Time,
CPU: resourceUtilization(model.ResourceTypeCPU, currentCpu.Timestamp.Time.UTC(), currentCpu.Request, currentCpu.Usage),
Memory: resourceUtilization(model.ResourceTypeMemory, currentMemory.Timestamp.Time.UTC(), currentMemory.Request, currentMemory.Usage),
CPU: resourceUtilization(model.ResourceTypeCPU, sCpu.utcTime, sCpu.request, sCpu.usage, sCpu.costOnlyRequest, sCpu.costOnlyUsage),
Memory: resourceUtilization(model.ResourceTypeMemory, sMem.utcTime, sMem.request, sMem.usage, sMem.costOnlyRequest, sMem.costOnlyUsage),
}, nil
}

Expand Down Expand Up @@ -288,7 +291,7 @@ func (c *client) resourceUtilizationForApp(ctx context.Context, resourceType mod
utilizationMap := initUtilizationMap(s, e)
for _, row := range rows {
ts := row.Timestamp.Time.UTC()
utilizationMap[ts] = resourceUtilization(resourceType, ts, row.Request, row.Usage)
utilizationMap[ts] = resourceUtilization(resourceType, ts, row.Request, row.Usage, row.Request, row.Usage)
}

data := make([]*model.ResourceUtilization, 0)
Expand Down Expand Up @@ -335,7 +338,7 @@ func (c *client) resourceUtilizationForTeam(ctx context.Context, resourceType mo
utilizationMap := initUtilizationMap(s, e)
for _, row := range rows {
ts := row.Timestamp.Time.UTC()
utilizationMap[ts] = resourceUtilization(resourceType, ts, row.Request, row.Usage)
utilizationMap[ts] = resourceUtilization(resourceType, ts, row.Request, row.Usage, row.Request, row.Usage)
}

data := make([]*model.ResourceUtilization, 0)
Expand Down Expand Up @@ -409,14 +412,14 @@ func getDateRange(from, to pgtype.Timestamptz) *model.ResourceUtilizationDateRan
}

// resourceUtilization will return a resource utilization model
func resourceUtilization(resource model.ResourceType, ts time.Time, request, usage float64) model.ResourceUtilization {
func resourceUtilization(resource model.ResourceType, ts time.Time, request, usage, costRequest, costUsage float64) model.ResourceUtilization {
var utilization float64
if request > 0 {
utilization = usage / request * 100
}

requestCost := costPerHour(resource.ToDatabaseEnum(), request)
usageCost := costPerHour(resource.ToDatabaseEnum(), usage)
requestCost := costPerHour(resource.ToDatabaseEnum(), costRequest)
usageCost := costPerHour(resource.ToDatabaseEnum(), costUsage)
overageCostPerHour := requestCost - usageCost

return model.ResourceUtilization{
Expand Down Expand Up @@ -449,3 +452,32 @@ func initUtilizationMap(start, end time.Time) map[time.Time]model.ResourceUtiliz
}
return utilization
}

type splitResource struct {
request float64
usage float64
costOnlyRequest float64
costOnlyUsage float64
utcTime time.Time
}

func joinSpecificRows(r []*gensql.SpecificResourceUtilizationForTeamRow) splitResource {
var request, usage, costOnlyRequest, costOnlyUsage float64
var utcTime time.Time
for _, row := range r {
utcTime = row.Timestamp.Time.UTC()
request += row.Request
usage += row.Usage
if row.UsableForCost {
costOnlyRequest += row.Request
costOnlyUsage += row.Usage
}
}
return splitResource{
request: request,
usage: usage,
costOnlyRequest: costOnlyRequest,
costOnlyUsage: costOnlyUsage,
utcTime: utcTime,
}
}

0 comments on commit 1c675d5

Please sign in to comment.