Skip to content

Commit

Permalink
base, licenseccl: Revise resolution strategy for LicenseTTL
Browse files Browse the repository at this point in the history
Previously, for resolving the cluster's license expiry we relied on a metric
whose value was regularly ticked down by an async task. This change seeks to
only the resolve value at read time by reading directly from the cluster
settings when its requested.

Release note: None

Fixes: CRDB-40592
Epic: CRDB-8035
  • Loading branch information
angles-n-daemons committed Sep 11, 2024
1 parent 6ce3baa commit 1b41fe1
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 63 deletions.
28 changes: 14 additions & 14 deletions pkg/base/license.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (

"github.com/cockroachdb/cockroach/pkg/settings/cluster"
"github.com/cockroachdb/cockroach/pkg/util/metric"
"github.com/cockroachdb/cockroach/pkg/util/stop"
"github.com/cockroachdb/cockroach/pkg/util/timeutil"
"github.com/cockroachdb/cockroach/pkg/util/uuid"
"github.com/cockroachdb/errors"
Expand All @@ -39,31 +38,32 @@ var CCLDistributionAndEnterpriseEnabled = func(st *cluster.Settings, clusterID u
return CheckEnterpriseEnabled(st, clusterID, "" /* feature */) == nil
}

var licenseTTLMetadata = metric.Metadata{
var LicenseTTLMetadata = metric.Metadata{
// This metric name isn't namespaced for backwards
// compatibility. The prior version of this metric was manually
// inserted into the prometheus output
Name: "seconds_until_enterprise_license_expiry",
Help: "Seconds until enterprise license expiry (0 if no license present or running without enterprise features)",
Help: "Seconds until license expiry (0 if no license present)",
Measurement: "Seconds",
Unit: metric.Unit_SECONDS,
}

// LicenseTTL is a metric gauge that measures the number of seconds
// until the current enterprise license (if any) expires.
var LicenseTTL = metric.NewGauge(licenseTTLMetadata)
var AdditionalLicenseTTLMetadata = metric.Metadata{
Name: "seconds_until_license_expiry",
Help: "Seconds until license expiry (0 if no license present)",
Measurement: "Seconds",
Unit: metric.Unit_SECONDS,
}

// UpdateMetricOnLicenseChange is a function that's called on startup
// in order to connect the enterprise license setting update to the
// prometheus metric provided as an argument.
var UpdateMetricOnLicenseChange = func(
// GetLicenseTTL is a function which returns the TTL for the active cluster.
// The implementation here returns 0, but if utilccl is started this function is
// overridden with an appropriate getter.
var GetLicenseTTL = func(
ctx context.Context,
st *cluster.Settings,
metric *metric.Gauge,
ts timeutil.TimeSource,
stopper *stop.Stopper,
) error {
return nil
) int64 {
return 0
}

// LicenseType returns what type of license the cluster is running with, or
Expand Down
2 changes: 1 addition & 1 deletion pkg/ccl/ccl_init.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func init() {
// this `ccl` pkg.
base.CheckEnterpriseEnabled = utilccl.CheckEnterpriseEnabled
base.LicenseType = utilccl.GetLicenseType
base.UpdateMetricOnLicenseChange = utilccl.UpdateMetricOnLicenseChange
base.GetLicenseTTL = utilccl.GetLicenseTTL
server.ApplyTenantLicense = utilccl.ApplyTenantLicense
license.RegisterCallbackOnLicenseChange = utilccl.RegisterCallbackOnLicenseChange
}
Expand Down
2 changes: 0 additions & 2 deletions pkg/ccl/utilccl/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ go_library(
"//pkg/sql/sem/tree",
"//pkg/util/envutil",
"//pkg/util/log",
"//pkg/util/metric",
"//pkg/util/stop",
"//pkg/util/timeutil",
"//pkg/util/uuid",
"@com_github_cockroachdb_errors//:errors",
Expand Down
45 changes: 9 additions & 36 deletions pkg/ccl/utilccl/license_check.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ import (
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror"
"github.com/cockroachdb/cockroach/pkg/util/envutil"
"github.com/cockroachdb/cockroach/pkg/util/log"
"github.com/cockroachdb/cockroach/pkg/util/metric"
"github.com/cockroachdb/cockroach/pkg/util/stop"
"github.com/cockroachdb/cockroach/pkg/util/timeutil"
"github.com/cockroachdb/cockroach/pkg/util/uuid"
"github.com/cockroachdb/errors"
Expand Down Expand Up @@ -149,49 +147,24 @@ func IsEnterpriseEnabled(st *cluster.Settings, cluster uuid.UUID, feature string
st, timeutil.Now(), cluster, feature, false /* withDetails */) == nil
}

var licenseMetricUpdateFrequency = 1 * time.Minute

// UpdateMetricOnLicenseChange starts a task to periodically update
// the given metric with the seconds remaining until license expiry.
func UpdateMetricOnLicenseChange(
// GetLicenseTTL is a function which returns the TTL for the active cluster.
// This is done by reading the license information from the cluster settings
// and subtracting the epoch from the expiry timestamp.
var GetLicenseTTL = func(
ctx context.Context,
st *cluster.Settings,
metric *metric.Gauge,
ts timeutil.TimeSource,
stopper *stop.Stopper,
) error {
enterpriseLicense.SetOnChange(&st.SV, func(ctx context.Context) {
updateMetricWithLicenseTTL(ctx, st, metric, ts)
})
return stopper.RunAsyncTask(ctx, "write-license-expiry-metric", func(ctx context.Context) {
ticker := time.NewTicker(licenseMetricUpdateFrequency)
defer ticker.Stop()
for {
select {
case <-ticker.C:
updateMetricWithLicenseTTL(ctx, st, metric, ts)
case <-stopper.ShouldQuiesce():
return
}
}
})
}

func updateMetricWithLicenseTTL(
ctx context.Context, st *cluster.Settings, metric *metric.Gauge, ts timeutil.TimeSource,
) {
) int64 {
license, err := getLicense(st)
if err != nil {
log.Errorf(ctx, "unable to update license expiry metric: %v", err)
metric.Update(0)
return
log.Errorf(ctx, "unable to find license: %v", err)
return 0
}
if license == nil {
metric.Update(0)
return
return 0
}
sec := timeutil.Unix(license.ValidUntilUnixSec, 0).Sub(ts.Now()).Seconds()
metric.Update(int64(sec))
return int64(sec)
}

// AllCCLCodeImported is set by the `ccl` pkg in an init(), thereby
Expand Down
5 changes: 1 addition & 4 deletions pkg/ccl/utilccl/license_check_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,9 +187,6 @@ func TestTimeToEnterpriseLicenseExpiry(t *testing.T) {
defer stopper.Stop(ctx)
manualTime := timeutil.NewManualTime(t0)

err := UpdateMetricOnLicenseChange(context.Background(), st, base.LicenseTTL, manualTime, stopper)
require.NoError(t, err)

for _, tc := range []struct {
desc string
lic string
Expand All @@ -205,7 +202,7 @@ func TestTimeToEnterpriseLicenseExpiry(t *testing.T) {
if err := setLicense(ctx, updater, tc.lic); err != nil {
t.Fatal(err)
}
actual := base.LicenseTTL.Value()
actual := base.GetLicenseTTL(context.Background(), st, manualTime)
require.Equal(t, tc.ttlSeconds, actual)
})
}
Expand Down
11 changes: 6 additions & 5 deletions pkg/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -387,11 +387,12 @@ func NewServer(cfg Config, stopper *stop.Stopper) (*Server, error) {
// started via the server controller.
cfg.RuntimeStatSampler = runtimeSampler

registry.AddMetric(base.LicenseTTL)
err = base.UpdateMetricOnLicenseChange(ctx, cfg.Settings, base.LicenseTTL, timeutil.DefaultTimeSource{}, stopper)
if err != nil {
log.Errorf(ctx, "unable to initialize periodic license metric update: %v", err)
}
registry.AddMetric(metric.NewFunctionalGauge(base.LicenseTTLMetadata, func() int64 {
return base.GetLicenseTTL(ctx, cfg.Settings, timeutil.DefaultTimeSource{})
}))
registry.AddMetric(metric.NewFunctionalGauge(base.AdditionalLicenseTTLMetadata, func() int64 {
return base.GetLicenseTTL(ctx, cfg.Settings, timeutil.DefaultTimeSource{})
}))

// Create and add KV metric rules.
kvserver.CreateAndAddRules(ctx, ruleRegistry)
Expand Down
8 changes: 7 additions & 1 deletion pkg/ts/catalog/chart_catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,11 +181,17 @@ var charts = []sectionDescription{
Metrics: []string{"node-id"},
},
{
Title: "License TTL",
Title: "Enterprise License TTL",
Downsampler: DescribeAggregator_MIN,
Percentiles: false,
Metrics: []string{"seconds_until_enterprise_license_expiry"},
},
{
Title: "License TTL",
Downsampler: DescribeAggregator_MIN,
Percentiles: false,
Metrics: []string{"seconds_until_license_expiry"},
},
},
},
{
Expand Down

0 comments on commit 1b41fe1

Please sign in to comment.