Skip to content
This repository has been archived by the owner on Mar 16, 2024. It is now read-only.

Commit

Permalink
add: scarf pulse and heartbeat
Browse files Browse the repository at this point in the history
Signed-off-by: Thorsten Klein <[email protected]>
  • Loading branch information
iwilltry42 committed Feb 19, 2024
1 parent 7a90a37 commit 18c37f8
Show file tree
Hide file tree
Showing 12 changed files with 128 additions and 1 deletion.
9 changes: 9 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,12 @@ linters:
- revive
fast: false
max-same-issues: 50

linters-settings:
revive:
ignore-generated-header: false
severity: warning
rules:
- name: unused-parameter
severity: warning
disabled: true
1 change: 1 addition & 0 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ builds:
- -s
- -w
- -X "github.com/acorn-io/runtime/pkg/version.Tag=v{{ .Version }}"
- -X 'github.com/acorn-io/runtime/pkg/usage.BaseURL="{{ .Env.USAGE_METRICS_URL }}"

universal_binaries:
- id: mac
Expand Down
1 change: 1 addition & 0 deletions docs/docs/100-reference/01-command-line/acorn_install.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ acorn install
--controller-memory string The memory to allocate to the runtime-controller in the format of <req>:<limit> (example 256Mi:1Gi)
--controller-replicas int acorn-controller deployment replica count
--controller-service-account-annotation strings annotation to apply to the acorn-system service account
--disable-usage-metrics Disable usage metrics collection (default is false)
--event-ttl string Amount of time an Acorn event will be stored before being deleted (default '168h' - 7 days)
--features strings Enable or disable features. (example foo=true,bar=false)
-h, --help help for install
Expand Down
3 changes: 3 additions & 0 deletions pkg/apis/api.acorn.io/v1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,9 @@ type Config struct {
RegistryCPU *string `json:"registryCPU" name:"registry-cpu" usage:"The CPU to allocate to the registry in the format of <req>:<limit> (example 200m:1000m)"`
IgnoreResourceRequirements *bool `json:"ignoreResourceRequirements" name:"ignore-resource-requirements" usage:"Ignore memory and CPU requests and limits, intended for local development (default is false)"`
RequireComputeClass *bool `json:"requireComputeClass" name:"require-compute-class" usage:"Require applications to have a Compute Class set (default is false)"`

// Usage Metrics
DisableUsageMetrics *bool `json:"disableUsageMetrics" name:"disable-usage-metrics" usage:"Disable usage metrics collection (default is false)"`
}

type EncryptionKey struct {
Expand Down
5 changes: 5 additions & 0 deletions pkg/apis/api.acorn.io/v1/zz_generated.deepcopy.go

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

6 changes: 6 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,9 @@ func complete(ctx context.Context, c *apiv1.Config, getter kclient.Reader, inclu
if c.AutoConfigureKarpenterDontEvictAnnotations == nil {
c.AutoConfigureKarpenterDontEvictAnnotations = profile.AutoConfigureKarpenterDontEvictAnnotations
}
if c.DisableUsageMetrics == nil {
c.DisableUsageMetrics = profile.DisableUsageMetrics
}
return nil
}

Expand Down Expand Up @@ -471,6 +474,9 @@ func merge(oldConfig, newConfig *apiv1.Config) *apiv1.Config {
if newConfig.AutoConfigureKarpenterDontEvictAnnotations != nil {
mergedConfig.AutoConfigureKarpenterDontEvictAnnotations = newConfig.AutoConfigureKarpenterDontEvictAnnotations
}
if newConfig.DisableUsageMetrics != nil {
mergedConfig.DisableUsageMetrics = newConfig.DisableUsageMetrics
}

return &mergedConfig
}
Expand Down
4 changes: 4 additions & 0 deletions pkg/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (
"github.com/acorn-io/runtime/pkg/logserver"
"github.com/acorn-io/runtime/pkg/scheme"
"github.com/acorn-io/runtime/pkg/system"
"github.com/acorn-io/runtime/pkg/usage"
"github.com/acorn-io/runtime/pkg/version"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/wait"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand Down Expand Up @@ -115,6 +117,8 @@ func (c *Controller) Start(ctx context.Context) error {

logserver.StartServerWithDefaults()

go usage.Heartbeat(ctx, c.client, usage.ComponentController, 24*time.Hour, version.Get().String())

// Every 5 minutes, delete EventInstances until only the most recent 1000 remain.
// Use c.Router.Backend() to ensure we hit the cache when possible.
// Note: the cache will only be populated for EventInstances if a handler for EventInstances has been registered.
Expand Down
5 changes: 5 additions & 0 deletions pkg/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ import (
"github.com/acorn-io/runtime/pkg/scheme"
"github.com/acorn-io/runtime/pkg/system"
"github.com/acorn-io/runtime/pkg/term"
"github.com/acorn-io/runtime/pkg/usage"
"github.com/acorn-io/runtime/pkg/version"
"github.com/acorn-io/z"
"github.com/pterm/pterm"
"github.com/sirupsen/logrus"
Expand Down Expand Up @@ -308,6 +310,9 @@ func Install(ctx context.Context, image string, opts *Options) error {
if !opts.Quiet {
pterm.Success.Println("Installation done")
}

_ = usage.Pulse(ctx, c, usage.ComponentCLI, usage.ActionInstall, version.Get().String())

return nil
}

Expand Down
9 changes: 8 additions & 1 deletion pkg/openapi/generated/openapi_generated.go

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

1 change: 1 addition & 0 deletions pkg/profiles/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,5 +76,6 @@ func defaultProfile() apiv1.Config {
IgnoreResourceRequirements: new(bool),
RequireComputeClass: new(bool),
AutoConfigureKarpenterDontEvictAnnotations: z.Pointer(true),
DisableUsageMetrics: new(bool),
}
}
2 changes: 2 additions & 0 deletions pkg/profiles/production.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,7 @@ func productionProfile() apiv1.Config {
conf.RequireComputeClass = z.Pointer(true)
conf.AutoConfigureKarpenterDontEvictAnnotations = z.Pointer(true)

conf.DisableUsageMetrics = z.Pointer(false)

return conf
}
83 changes: 83 additions & 0 deletions pkg/usage/usage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package usage

import (
"context"
"fmt"
"net/http"
"os"
"strings"
"time"

"github.com/acorn-io/runtime/pkg/config"
"github.com/acorn-io/runtime/pkg/version"
"github.com/acorn-io/z"
"github.com/sirupsen/logrus"
"k8s.io/apimachinery/pkg/util/wait"
kclient "sigs.k8s.io/controller-runtime/pkg/client"
)

type RuntimeComponent string
type RuntimeAction string

const (
BaseURL = ""

ComponentCLI RuntimeComponent = "cli"
ComponentAPIServer RuntimeComponent = "api-server"
ComponentController RuntimeComponent = "controller"

ActionInstall RuntimeAction = "install" // subpaths: /install/{version}

ActionHeartbeat RuntimeAction = "heartbeat" // subpaths: /heartbeat/{version}

EnvUsageMetrics = "ACORN_USAGE_METRICS"
)

func Pulse(ctx context.Context, c kclient.Client, component RuntimeComponent, action RuntimeAction, elements ...string) error {
if !UsageMetricsEnabled(ctx, c) {
return nil
}

url := fmt.Sprintf("%s/%s/%s", BaseURL, component, action)
for _, e := range elements {
url += "/" + e
}

resp, err := http.Get(url)
if err != nil {
return err
}

if resp.StatusCode != http.StatusOK {
return fmt.Errorf("unexpected status code: %d", resp.StatusCode)
}

return nil
}

func Heartbeat(ctx context.Context, c kclient.Client, component RuntimeComponent, interval time.Duration, elements ...string) {
wait.UntilWithContext(ctx, func(_ context.Context) {
err := Pulse(ctx, c, component, ActionHeartbeat, elements...)
if err != nil {
logrus.Warnf("failed to send heartbeat for %q: %v", component, err)
}
}, interval)
}

// UsageMetricsEnabled returns true if usage metrics are enabled.
// Usage Metrics are enabled by default, but are disabled by
// a) setting the ACORN_USAGE_METRICS environment variable to "disabled"
// b) setting the DisableUsageMetrics field in the acorn config to true
// c) running a development build (dirty or tag ending in -dev)
// d) running in an unofficial build (BaseURL is empty)
func UsageMetricsEnabled(ctx context.Context, c kclient.Client) bool {
enabled := true
if c != nil {
cfg, err := config.Get(ctx, c)
if err != nil {
return false
}
enabled = !z.Dereference(cfg.DisableUsageMetrics)
}
return enabled && os.Getenv(EnvUsageMetrics) != "disabled" && !version.Get().Dirty && !strings.HasSuffix(version.Get().Tag, "-dev") && BaseURL != ""
}

0 comments on commit 18c37f8

Please sign in to comment.