Skip to content

Commit 19b4375

Browse files
cstocktonChris Stockton
andauthored
chore: version gauge code coverage and error improvements (#2379)
Improves error messages and adds some unit tests to bring code coverage to 100%. Co-authored-by: Chris Stockton <chris.stockton@supabase.io>
1 parent 911ad0b commit 19b4375

2 files changed

Lines changed: 75 additions & 17 deletions

File tree

internal/utilities/version.go

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,37 +23,55 @@ func InitVersionMetrics(ctx context.Context) error {
2323
func initVersionMetrics(ctx context.Context, ver string) error {
2424
vi, err := parseSemver(ver)
2525
if err != nil {
26-
vi = &versionInfo{}
26+
const msg = "initVersionMetrics: unable to parse version %q: %w"
27+
return fmt.Errorf(msg, ver, err)
2728
}
2829

2930
if err := initMetrics(ctx, vi); err != nil {
30-
return err
31+
const msg = "initVersionMetrics: unable to initialize version %q: %w"
32+
return fmt.Errorf(msg, ver, err)
3133
}
3234
return nil
3335
}
3436

35-
func initGauge(ctx context.Context, typ string, val uint64) error {
37+
func initGauge(
38+
ctx context.Context,
39+
typ string,
40+
val uint64,
41+
gaugeFunc initGaugeFunc,
42+
) error {
3643
name := fmt.Sprintf("global_auth_version_%v", typ)
3744
desc := fmt.Sprintf("Set to this auth servers %v version number.", typ)
3845

39-
g, err := otel.Meter("gotrue").Int64Gauge(name, metric.WithDescription(desc))
46+
g, err := gaugeFunc(name, metric.WithDescription(desc))
4047
if err != nil {
41-
return err
48+
const msg = "initGauge: part %q (%v) otel error: %w"
49+
return fmt.Errorf(msg, typ, val, err)
4250
}
4351
if val > math.MaxInt64 {
44-
return errors.New("value is > math.MaxInt64")
52+
const msg = "initGauge: part %q (%v) value > math.MaxInt64"
53+
return fmt.Errorf(msg, typ, val)
4554
}
4655

4756
g.Record(ctx, int64(val))
4857
return nil
4958
}
5059

60+
type initGaugeFunc func(
61+
name string,
62+
options ...metric.Int64GaugeOption,
63+
) (metric.Int64Gauge, error)
64+
65+
func initGaugeOtel(name string, options ...metric.Int64GaugeOption) (metric.Int64Gauge, error) {
66+
return otel.Meter("gotrue").Int64Gauge(name, options...)
67+
}
68+
5169
func initMetrics(ctx context.Context, vi *versionInfo) error {
5270
return errors.Join(
53-
initGauge(ctx, "major", vi.Major),
54-
initGauge(ctx, "minor", vi.Minor),
55-
initGauge(ctx, "patch", vi.Patch),
56-
initGauge(ctx, "rc", vi.RC),
71+
initGauge(ctx, "major", vi.Major, initGaugeOtel),
72+
initGauge(ctx, "minor", vi.Minor, initGaugeOtel),
73+
initGauge(ctx, "patch", vi.Patch, initGaugeOtel),
74+
initGauge(ctx, "rc", vi.RC, initGaugeOtel),
5775
)
5876
}
5977

internal/utilities/version_test.go

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,19 @@ package utilities
22

33
import (
44
"context"
5+
"errors"
6+
"fmt"
7+
"math"
8+
"strconv"
59
"strings"
610
"testing"
711
"time"
812

913
"github.com/stretchr/testify/require"
14+
"go.opentelemetry.io/otel/metric"
1015
)
1116

12-
func TestInitVersionMetrics(t *testing.T) {
17+
func TestVersionInitVersionMetrics(t *testing.T) {
1318
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
1419
defer cancel()
1520

@@ -28,31 +33,63 @@ func TestInitVersionMetrics(t *testing.T) {
2833
}
2934
}
3035

31-
const ver = "rc2.187.3-rc.23-g33b87ae0"
36+
const validVer = "rc2.187.3-rc.23-g33b87ae0"
3237

3338
{
34-
vi, err := parseSemver(ver)
39+
vi, err := parseSemver(validVer)
3540
require.NoError(t, err)
3641
check(vi)
3742
}
3843

3944
{
40-
err := initVersionMetrics(ctx, ver)
45+
err := initVersionMetrics(ctx, validVer)
4146
require.NoError(t, err)
4247
}
4348

49+
{
50+
err := initVersionMetrics(ctx, "invalid")
51+
require.Error(t, err)
52+
const exp = "initVersionMetrics: unable to parse version"
53+
if got := err.Error(); !strings.Contains(got, exp) {
54+
t.Fatalf("exp err %q to contain %q", got, exp)
55+
}
56+
}
57+
58+
{
59+
max := strconv.AppendUint(nil, math.MaxUint64, 10)
60+
ver := fmt.Sprintf("%v.%v.%s", 2, 187, max)
61+
err := initVersionMetrics(ctx, ver)
62+
require.Error(t, err)
63+
if exp, got := "math.MaxInt64", err.Error(); !strings.Contains(got, exp) {
64+
t.Fatalf("exp err %q to contain %q", got, exp)
65+
}
66+
}
67+
68+
{
69+
sentinel := errors.New("otel-sentinel")
70+
errFn := func(name string, options ...metric.Int64GaugeOption) (metric.Int64Gauge, error) {
71+
return nil, sentinel
72+
}
73+
74+
err := initGauge(ctx, "metric", 1, errFn)
75+
require.Error(t, err)
76+
if exp, got := sentinel.Error(), err.Error(); !strings.Contains(got, exp) {
77+
t.Fatalf("exp err %q to contain %q", got, exp)
78+
}
79+
}
80+
4481
func() {
4582
prev := Version
4683
defer func() { Version = prev }()
47-
Version = ver
84+
Version = validVer
4885

4986
err := InitVersionMetrics(ctx)
5087
require.NoError(t, err)
5188
}()
5289

5390
}
5491

55-
func TestParseSemver(t *testing.T) {
92+
func TestVersionParseSemver(t *testing.T) {
5693
cases := []struct {
5794
str, err string
5895
maj, min, pat, rc uint64
@@ -115,6 +152,9 @@ func TestParseSemver(t *testing.T) {
115152
{str: "2.165.1-rc.1", maj: 2, min: 165, pat: 1, rc: 1},
116153
{str: "2.165.1-rc1", maj: 2, min: 165, pat: 1, rc: 1},
117154

155+
{str: "2.165.1-rc.1.5", maj: 2, min: 165, pat: 1, rc: 1},
156+
{str: "2.165.1-rc1.5", maj: 2, min: 165, pat: 1, rc: 1},
157+
118158
{str: "", err: "Invalid Semantic Version"},
119159
{str: "abc", err: "Invalid Semantic Version"},
120160
}
@@ -144,7 +184,7 @@ func TestParseSemver(t *testing.T) {
144184
t.Fatal("exp non-nil err")
145185
}
146186
if exp, got := tc.err, err.Error(); !strings.Contains(got, exp) {
147-
t.Fatalf("exp ")
187+
t.Fatalf("exp err %q to contain %q", got, exp)
148188
}
149189
continue
150190
}

0 commit comments

Comments
 (0)