Files
wehub-resource-sync 75f3dd141c
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CI and Release / lint-frontend (push) Has been cancelled
CI and Release / dockerfile-scan (push) Has been cancelled
CI and Release / test-frontend (push) Has been cancelled
CI and Release / lint-verification-agent (push) Has been cancelled
CI and Release / test-verification-agent (push) Has been cancelled
CI and Release / e2e-verification-agent (push) Has been cancelled
CI and Release / test-backend (push) Has been cancelled
CI and Release / build-dev-image (push) Has been cancelled
CI and Release / push-dev-image (push) Has been cancelled
CI and Release / build-image (push) Has been cancelled
CI and Release / build-verification-image (push) Has been cancelled
CI and Release / determine-version (push) Has been cancelled
CI and Release / push-image (push) Has been cancelled
CI and Release / push-verification-image (12) (push) Has been cancelled
CI and Release / lint-backend (push) Has been cancelled
CI and Release / push-verification-image (17) (push) Has been cancelled
CI and Release / push-verification-image (18) (push) Has been cancelled
CI and Release / release (push) Has been cancelled
CI and Release / publish-helm-chart (push) Has been cancelled
CI and Release / push-verification-image (13) (push) Has been cancelled
CI and Release / push-verification-image (14) (push) Has been cancelled
CI and Release / push-verification-image (15) (push) Has been cancelled
CI and Release / push-verification-image (16) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:11:07 +08:00

83 lines
2.1 KiB
Go

package telemetry
import (
"encoding/json"
"log/slog"
"os"
"path/filepath"
"time"
"github.com/google/uuid"
)
type Instance struct {
InstanceID string `json:"instanceID"`
InstalledAt string `json:"installedAt"`
}
type InstanceFileLoader struct {
path string
logger *slog.Logger
}
func NewInstanceFileLoader(path string, logger *slog.Logger) *InstanceFileLoader {
return &InstanceFileLoader{path: path, logger: logger}
}
// LoadOrCreate returns (instance, true) on success and (nil, false) when the
// file cannot be read or written. Telemetry is skipped on failure rather than
// falling back to an ephemeral UUID — phantom new instances on every restart
// would pollute the central counts.
func (l *InstanceFileLoader) LoadOrCreate() (*Instance, bool) {
data, err := os.ReadFile(l.path)
if err == nil {
var instance Instance
if err := json.Unmarshal(data, &instance); err != nil {
l.logger.Warn("telemetry instance file is corrupt; skipping telemetry",
"path", l.path, "error", err)
return nil, false
}
if instance.InstanceID == "" {
l.logger.Warn("telemetry instance file is missing instanceID; skipping telemetry",
"path", l.path)
return nil, false
}
return &instance, true
}
if !os.IsNotExist(err) {
l.logger.Warn("failed to read telemetry instance file; skipping telemetry",
"path", l.path, "error", err)
return nil, false
}
instance := &Instance{
InstanceID: uuid.New().String(),
InstalledAt: time.Now().UTC().Format("2006-01-02"),
}
encoded, err := json.Marshal(instance)
if err != nil {
l.logger.Warn("failed to encode telemetry instance file; skipping telemetry",
"path", l.path, "error", err)
return nil, false
}
if err := os.MkdirAll(filepath.Dir(l.path), 0o700); err != nil {
l.logger.Warn("failed to create telemetry instance file directory; skipping telemetry",
"path", l.path, "error", err)
return nil, false
}
if err := os.WriteFile(l.path, encoded, 0o600); err != nil {
l.logger.Warn("failed to write telemetry instance file; skipping telemetry",
"path", l.path, "error", err)
return nil, false
}
return instance, true
}