Help us shape the future of Go! Take the 2026 Go Developer Survey

telemetry

package
v0.0.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 30, 2026 License: AGPL-3.0 Imports: 13 Imported by: 0

Documentation

Overview

Package telemetry sends strictly opt-in, allowlisted usage events to PostHog. It is off by default, DO_NOT_TRACK always wins, and sending never blocks the CLI for more than a short bounded flush or changes its output.

The official posthog-go client is intentionally not used: it starts background goroutines with retry/backoff and batching we do not need for one event per process. A single bounded HTTPS POST is simpler to reason about for the never-block rule and adds no dependencies.

Index

Constants

View Source
const (
	DefaultKey  = "phc_X9QM3tEAsU8bp71rq0wlODLXWnrX0AiRM9zHzklbiEp"
	DefaultHost = "https://piaget.icarus.tools"
	// FlushTimeout bounds the single send at process exit.
	FlushTimeout = 2 * time.Second
	EventCommand = "cli_command"
	Source       = "oku-cli"
)

Public, write-only project key and first-party ingestion proxy (same project as the Oku web app).

Variables

View Source
var AllowedProperties = map[string]string{
	"$lib":                    "always \"oku-cli\"",
	"source":                  "always \"oku-cli\"",
	"command":                 "command path, e.g. \"swap prepare\"",
	"success":                 "true or false",
	"error_code":              "structured error code, e.g. REJECTED (failures only)",
	"retryable":               "whether the error is marked retryable (failures only)",
	"duration_ms":             "command wall time in milliseconds",
	"cli_version":             "oku version",
	"cli_commit":              "oku build commit",
	"os":                      "GOOS, e.g. linux",
	"arch":                    "GOARCH, e.g. amd64",
	"json":                    "whether --json was used",
	"invoked_by":              "mcp, tty or non_tty",
	"api_env":                 "prod, staging, local or custom (never the URL)",
	"chain_id":                "funds commands: source chain id",
	"destination_chain":       "funds commands: destination chain id",
	"route":                   "funds commands: route/bridge the CLI selected, else the --route value",
	"route_forced":            "funds commands: whether --route forced the route",
	"intent":                  "funds commands: whether intent routes were allowed",
	"amount_source":           "funds commands: max or exact (never the amount)",
	"from_kind":               "funds commands: native or erc20 (never the address)",
	"to_kind":                 "funds commands: native or erc20 (never the address)",
	"routes_considered":       "funds REJECTED failures: number of routes considered",
	"routes_rejected":         "funds REJECTED failures: number of routes rejected",
	"route_attempts":          "funds REJECTED failures: number of quote attempts",
	"route_rejections":        "funds REJECTED failures: rejection category counts only (known categories, else other), e.g. amount_mismatch:2,not_answered:1",
	"$process_person_profile": "always false (no person profiles)",
}

AllowedProperties is the exhaustive set of property keys that may be sent. Anything else is dropped by Build. Keep docs/telemetry.md in sync.

View Source
var UserAgent = "oku-cli"

Send posts one event with a hard timeout. All errors are returned for tests but callers must ignore them. UserAgent identifies the CLI to the ingestion proxy. Cloudflare in front of the proxy blocks Go's default "Go-http-client" agent with a 403.

Functions

func Build

func Build(props map[string]any) map[string]any

Build filters props to the allowlist and drops any value that is not a bool, int, or short safe token string. Strings that look like addresses or decimal amounts are dropped as a belt-and-braces guard.

func Categories

func Categories(counts map[string]int) string

Categories formats rejection category counts as "a:2,b:1", keeping only snake_case category names.

func Endpoint

func Endpoint(getenv func(string) string) (host, key string)

Endpoint returns host and key, honoring OKU_TELEMETRY_HOST/KEY.

func EnsureInstallID

func EnsureInstallID(stateDir string) (string, error)

EnsureInstallID returns the install ID, creating a random UUIDv4 if absent.

func InstallID

func InstallID(stateDir string) string

InstallID reads the random install ID, or "" if none exists.

func RemoveInstallID

func RemoveInstallID(stateDir string) error

RemoveInstallID deletes the install ID so a later enable starts fresh.

func Send

func Send(ctx context.Context, host, key, distinctID, event string, props map[string]any, now time.Time) error

Types

type Reason

type Reason string

Reason explains why telemetry is on or off.

const (
	ReasonDefault    Reason = "default"
	ReasonConfig     Reason = "config"
	ReasonEnv        Reason = "env OKU_TELEMETRY"
	ReasonDoNotTrack Reason = "env DO_NOT_TRACK"
)

func Resolve

func Resolve(getenv func(string) string, configEnabled bool) (bool, Reason)

Resolve applies precedence: DO_NOT_TRACK forces off, then OKU_TELEMETRY, then the config value, then off.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL