Skip to content

Commit

Permalink
Add materialized view for resource utilization and refresh it
Browse files Browse the repository at this point in the history
Co-authored-by: Thomas Krampl <[email protected]>
  • Loading branch information
frodesundby and thokra-nav committed Apr 16, 2024
1 parent fe853f9 commit 34baf0f
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 32 deletions.
46 changes: 46 additions & 0 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: 2 additions & 0 deletions internal/database/gensql/querier.go

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

23 changes: 11 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.

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
-- +goose Up

-- Team range for resource utilization
DROP MATERIALIZED VIEW IF EXISTS resource_team_range;
CREATE MATERIALIZED VIEW resource_team_range AS
SELECT
team_slug,
MIN(timestamp)::timestamptz AS "from",
MAX(timestamp)::timestamptz AS "to"
FROM
resource_utilization_metrics
GROUP BY
team_slug;

CREATE UNIQUE INDEX ON resource_team_range (team_slug);
46 changes: 46 additions & 0 deletions internal/database/mock_database.go

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

17 changes: 5 additions & 12 deletions internal/database/queries/resourceusage.sql
Original file line number Diff line number Diff line change
@@ -1,17 +1,6 @@
-- ResourceUtilizationRangeForTeam will return the min and max timestamps for a specific team.
-- name: ResourceUtilizationRangeForTeam :one
WITH team_range AS (
SELECT timestamp
FROM
resource_utilization_metrics
WHERE
team_slug = @team_slug
)
SELECT
MIN(timestamp)::timestamptz AS "from",
MAX(timestamp)::timestamptz AS "to"
FROM
team_range;
SELECT "from", "to" FROM resource_team_range WHERE team_slug = @team_slug;

-- ResourceUtilizationRangeForApp will return the min and max timestamps for a specific app.
-- name: ResourceUtilizationRangeForApp :one
Expand Down Expand Up @@ -134,3 +123,7 @@ WHERE
AND timestamp >= sqlc.arg(timestamp)::timestamptz - INTERVAL '1 week'
AND timestamp < sqlc.arg(timestamp)::timestamptz
AND request > usage;

-- Refresh materialized view resource_team_range
-- name: RefreshResourceTeamRange :exec
REFRESH MATERIALIZED VIEW CONCURRENTLY resource_team_range;
6 changes: 6 additions & 0 deletions internal/database/resource_utilization.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type ResourceUtilizationRepo interface {
ResourceUtilizationOverageForTeam(ctx context.Context, teamSlug slug.Slug, timestamp pgtype.Timestamptz, resourceType gensql.ResourceType) ([]*gensql.ResourceUtilizationOverageForTeamRow, error)
ResourceUtilizationRangeForApp(ctx context.Context, environment string, teamSlug slug.Slug, app string) (*gensql.ResourceUtilizationRangeForAppRow, error)
ResourceUtilizationRangeForTeam(ctx context.Context, teamSlug slug.Slug) (*gensql.ResourceUtilizationRangeForTeamRow, error)
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)
Expand All @@ -27,6 +28,11 @@ func (d *database) ResourceUtilizationUpsert(ctx context.Context, arg []gensql.R
return d.querier.ResourceUtilizationUpsert(ctx, arg)
}

func (d *database) ResourceUtilizationRefresh(ctx context.Context) error {
return d.querier.RefreshResourceTeamRange(ctx)
}


func (d *database) AverageResourceUtilizationForTeam(ctx context.Context, teamSlug slug.Slug, resourceType gensql.ResourceType, timestamp pgtype.Timestamptz) (*gensql.AverageResourceUtilizationForTeamRow, error) {
return d.querier.AverageResourceUtilizationForTeam(ctx, gensql.AverageResourceUtilizationForTeamParams{
TeamSlug: teamSlug,
Expand Down
31 changes: 23 additions & 8 deletions internal/resourceusage/updater.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import (
promv1 "github.com/prometheus/client_golang/api/prometheus/v1"
prom "github.com/prometheus/common/model"
"github.com/sirupsen/logrus"
"go.opentelemetry.io/otel"
metricapi "go.opentelemetry.io/otel/metric"
)

type (
Expand All @@ -23,10 +25,11 @@ type (
)

type Updater struct {
k8sClient *k8s.Client
db database.Database
promClients map[string]promv1.API
log logrus.FieldLogger
k8sClient *k8s.Client
db database.Database
promClients map[string]promv1.API
log logrus.FieldLogger
errorCounter metricapi.Int64Counter
}

const (
Expand Down Expand Up @@ -60,11 +63,18 @@ var (

// NewUpdater creates a new resourceusage updater
func NewUpdater(k8sClient *k8s.Client, promClients map[string]promv1.API, db database.Database, log logrus.FieldLogger) *Updater {
meter := otel.Meter("resourceusage")
counter, err := meter.Int64Counter("mat_view_update_error", metricapi.WithDescription("Counter for errors when updating materialized view"))
if err != nil {
log.Fatalf("failed to create counter: %v", err)
}
counter.Add(context.Background(), 1)
return &Updater{
k8sClient: k8sClient,
db: db,
promClients: promClients,
log: log,
k8sClient: k8sClient,
db: db,
promClients: promClients,
log: log,
errorCounter: counter,
}
}

Expand Down Expand Up @@ -108,6 +118,11 @@ func (u *Updater) UpdateResourceUsage(ctx context.Context) (rowsUpserted int, er
}
}

if err := u.db.ResourceUtilizationRefresh(ctx); err != nil {
u.log.WithError(err).Errorf("unable to refresh resource team range")
u.errorCounter.Add(ctx, 1)
}

return rowsUpserted, nil
}

Expand Down

0 comments on commit 34baf0f

Please sign in to comment.