Skip to content

Commit 075d856

Browse files
easyCZroboquat
authored andcommitted
[usage] Track last compelted ledger job time
1 parent 40b89ce commit 075d856

File tree

3 files changed

+83
-51
lines changed

3 files changed

+83
-51
lines changed

components/usage/pkg/scheduler/job.go

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,9 @@
55
package scheduler
66

77
import (
8-
"context"
98
"fmt"
109
"github.com/gitpod-io/gitpod/common-go/log"
11-
v1 "github.com/gitpod-io/gitpod/usage-api/v1"
1210
"github.com/robfig/cron"
13-
"google.golang.org/protobuf/types/known/timestamppb"
1411
"time"
1512
)
1613

@@ -37,51 +34,6 @@ func NewPeriodicJobSpec(period time.Duration, id string, job Job) (JobSpec, erro
3734
}, nil
3835
}
3936

40-
func NewLedgerTriggerJobSpec(schedule time.Duration, job Job) (JobSpec, error) {
41-
return NewPeriodicJobSpec(schedule, "ledger", WithoutConcurrentRun(job))
42-
}
43-
44-
func NewLedgerTrigger(usageClient v1.UsageServiceClient, billingClient v1.BillingServiceClient) *LedgerJob {
45-
return &LedgerJob{
46-
usageClient: usageClient,
47-
billingClient: billingClient,
48-
}
49-
}
50-
51-
type LedgerJob struct {
52-
usageClient v1.UsageServiceClient
53-
billingClient v1.BillingServiceClient
54-
}
55-
56-
func (r *LedgerJob) Run() (err error) {
57-
ctx := context.Background()
58-
now := time.Now().UTC()
59-
hourAgo := now.Add(-1 * time.Hour)
60-
61-
logger := log.
62-
WithField("from", hourAgo).
63-
WithField("to", now)
64-
65-
logger.Info("Running ledger job. Reconciling usage records.")
66-
_, err = r.usageClient.ReconcileUsage(ctx, &v1.ReconcileUsageRequest{
67-
From: timestamppb.New(hourAgo),
68-
To: timestamppb.New(now),
69-
})
70-
if err != nil {
71-
logger.WithError(err).Errorf("Failed to reconcile usage with ledger.")
72-
return fmt.Errorf("failed to reconcile usage with ledger: %w", err)
73-
}
74-
75-
logger.Info("Starting invoice reconciliation.")
76-
_, err = r.billingClient.ReconcileInvoices(ctx, &v1.ReconcileInvoicesRequest{})
77-
if err != nil {
78-
logger.WithError(err).Errorf("Failed to reconcile invoices.")
79-
return fmt.Errorf("failed to reconcile invoices: %w", err)
80-
}
81-
82-
return nil
83-
}
84-
8537
// WithoutConcurrentRun wraps a Job and ensures the job does not concurrently
8638
func WithoutConcurrentRun(j Job) Job {
8739
return &preventConcurrentInvocation{
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Copyright (c) 2022 Gitpod GmbH. All rights reserved.
2+
// Licensed under the GNU Affero General Public License (AGPL).
3+
// See License-AGPL.txt in the project root for license information.
4+
5+
package scheduler
6+
7+
import (
8+
"context"
9+
"fmt"
10+
"github.com/gitpod-io/gitpod/common-go/log"
11+
v1 "github.com/gitpod-io/gitpod/usage-api/v1"
12+
"google.golang.org/protobuf/types/known/timestamppb"
13+
"time"
14+
)
15+
16+
func NewLedgerTriggerJobSpec(schedule time.Duration, job Job) (JobSpec, error) {
17+
return NewPeriodicJobSpec(schedule, "ledger", WithoutConcurrentRun(job))
18+
}
19+
20+
func NewLedgerTrigger(usageClient v1.UsageServiceClient, billingClient v1.BillingServiceClient) *LedgerJob {
21+
return &LedgerJob{
22+
usageClient: usageClient,
23+
billingClient: billingClient,
24+
}
25+
}
26+
27+
type LedgerJob struct {
28+
usageClient v1.UsageServiceClient
29+
billingClient v1.BillingServiceClient
30+
}
31+
32+
func (r *LedgerJob) Run() (err error) {
33+
defer func() {
34+
reportLedgerCompleted(err)
35+
}()
36+
37+
ctx := context.Background()
38+
now := time.Now().UTC()
39+
hourAgo := now.Add(-1 * time.Hour)
40+
41+
logger := log.
42+
WithField("from", hourAgo).
43+
WithField("to", now)
44+
45+
logger.Info("Running ledger job. Reconciling usage records.")
46+
_, err = r.usageClient.ReconcileUsage(ctx, &v1.ReconcileUsageRequest{
47+
From: timestamppb.New(hourAgo),
48+
To: timestamppb.New(now),
49+
})
50+
if err != nil {
51+
logger.WithError(err).Errorf("Failed to reconcile usage with ledger.")
52+
return fmt.Errorf("failed to reconcile usage with ledger: %w", err)
53+
}
54+
55+
logger.Info("Starting invoice reconciliation.")
56+
_, err = r.billingClient.ReconcileInvoices(ctx, &v1.ReconcileInvoicesRequest{})
57+
if err != nil {
58+
logger.WithError(err).Errorf("Failed to reconcile invoices.")
59+
return fmt.Errorf("failed to reconcile invoices: %w", err)
60+
}
61+
62+
return nil
63+
}

components/usage/pkg/scheduler/reporter.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ var (
3131
Buckets: prometheus.LinearBuckets(30, 30, 10), // every 30 secs, starting at 30secs
3232
}, []string{"job", "outcome"})
3333

34+
ledgerLastCompletedTime = prometheus.NewGaugeVec(prometheus.GaugeOpts{
35+
Namespace: namespace,
36+
Subsystem: subsystem,
37+
Name: "ledger_last_completed_time",
38+
Help: "The last time the ledger scheduled job completed, by outcome",
39+
ConstLabels: nil,
40+
}, []string{"outcome"})
41+
3442
stoppedWithoutStoppingTime = prometheus.NewGauge(prometheus.GaugeOpts{
3543
Namespace: namespace,
3644
Subsystem: subsystem,
@@ -44,6 +52,7 @@ func RegisterMetrics(reg *prometheus.Registry) error {
4452
jobStartedSeconds,
4553
jobCompletedSeconds,
4654
stoppedWithoutStoppingTime,
55+
ledgerLastCompletedTime,
4756
}
4857
for _, metric := range metrics {
4958
err := reg.Register(metric)
@@ -60,9 +69,17 @@ func reportJobStarted(id string) {
6069
}
6170

6271
func reportJobCompleted(id string, duration time.Duration, err error) {
63-
outcome := "success"
72+
jobCompletedSeconds.WithLabelValues(id, outcomeFromErr(err)).Observe(duration.Seconds())
73+
}
74+
75+
func reportLedgerCompleted(err error) {
76+
ledgerLastCompletedTime.WithLabelValues(outcomeFromErr(err)).SetToCurrentTime()
77+
}
78+
79+
func outcomeFromErr(err error) string {
80+
out := "success"
6481
if err != nil {
65-
outcome = "error"
82+
out = "error"
6683
}
67-
jobCompletedSeconds.WithLabelValues(id, outcome).Observe(duration.Seconds())
84+
return out
6885
}

0 commit comments

Comments
 (0)