feat: anonymous usage telemetry via oss-telemetry

Send a single fire-and-forget ping at startup to help track adoption
and version spread. No persistent identifiers are collected.

main() is wrapped via runMain() so deferred Wait drains in-flight pings
before os.Exit.

Opt out via any of:
  DO_NOT_TRACK=1
  OSS_TELEMETRY_DISABLED=1
  KPORTAL_DISABLE_TELEMETRY=1
This commit is contained in:
2026-05-21 02:59:46 +01:00
parent 3f11219dc1
commit cda8b4be47
3 changed files with 19 additions and 107 deletions
+13 -3
View File
@@ -24,6 +24,7 @@ import (
"github.com/lukaszraczylo/kportal/internal/mdns"
"github.com/lukaszraczylo/kportal/internal/ui"
"github.com/lukaszraczylo/kportal/internal/version"
telemetry "github.com/lukaszraczylo/oss-telemetry"
"k8s.io/klog/v2"
)
@@ -96,10 +97,19 @@ func promptCreateConfig(path string, stdin io.Reader, stdout io.Writer) bool {
}
func main() {
os.Exit(runMain())
}
// runMain wraps the real entry point so that deferred cleanup (telemetry
// drain, signal context cancel) runs before the surrounding os.Exit.
func runMain() int {
telemetry.Send("kportal", appVersion)
defer telemetry.Wait(2 * time.Second)
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
code := run(ctx, os.Args[1:], os.Stdin, os.Stdout, os.Stderr)
cancel()
os.Exit(code)
defer cancel()
return run(ctx, os.Args[1:], os.Stdin, os.Stdout, os.Stderr)
}
// run is the testable entry point. It returns the desired process exit code