Documentation
¶
Overview ¶
Package telemetry reports that swarmcli is being used, and nothing about what it is used on.
What it sends is enumerated in `docs/license.md` under Privacy and is the whole of it: an install identifier, the version and edition, the operating system and architecture, how the binary was installed, and whether it is the TUI or the controller. Deliberately absent, and listed here so the next person adding a field has to argue past it: hostnames, cluster or node names, service, stack and image names, command arguments, error text, and the address the request came from. Those describe a customer's infrastructure, and the licence documentation promises "how many, never which ones".
It is on by default and `SWARMCLI_TELEMETRY=off` switches it off. The update check is a separate thing and survives that switch — see Client.
Index ¶
Constants ¶
const ( // Env is the one variable that governs the startup request, and it has // three states rather than two — see State. // // Spelled as a value rather than as SWARMCLI_DISABLE_TELEMETRY so that // `SWARMCLI_TELEMETRY=off` reads the way people write it, and so the third // state had somewhere to go without a second variable. Env = "SWARMCLI_TELEMETRY" // DefaultURL is the telemetry endpoint, which also answers the update check. DefaultURL = "https://swarmcli.io/api/v1/telemetry" // FallbackURL is the original update check, and the whole of what is called // when telemetry is off: it carries no install id and nothing about the // machine. FallbackURL = "https://swarmcli.io/api/v1/version" )
const ( EventStarted = "swarmcli_started" EventHeartbeat = "swarmcli_heartbeat" )
Events. A closed set matching the server's; an unknown name is refused there.
const ( ModeTUI = "tui" ModeCLI = "cli" ModeCD = "cd" )
Modes. Which of the three products is asking.
const ( MethodBrew = "brew" MethodScoop = "scoop" MethodDocker = "docker" MethodSource = "source" MethodTarball = "tarball" MethodUnknown = "unknown" )
Install methods. A closed set, matching the server's zod enum: a value outside it is refused there, so inventing one here would silently drop the whole event rather than just the field.
const ( NoticeTitle = "Usage reporting is on" NoticeBody = `` /* 743-byte string literal not displayed */ )
NoticeTitle and NoticeBody are the first-run disclosure.
**This is the half of opt-out that makes it legitimate.** A default-on reporter with no notice is the thing people are right to object to; the difference between that and this is that the first run says what is being sent, before anything has been sent, and says how to stop it.
Written to be read in three seconds, so it enumerates rather than explains. The enumeration is the point: it is the same list as `docs/license.md` and the same list the server's schema accepts, and if the three ever disagree the documentation is wrong rather than the reader.
It names what is *not* sent as well, because that is the question somebody running this against a production swarm actually has, and answering it in the notice is cheaper than having them find the documentation to be reassured.
Variables ¶
This section is empty.
Functions ¶
func InstallID ¶
func InstallID() string
InstallID returns this installation's identifier, creating and persisting one on first use.
Returns "" when no identity can be stored — no home directory, an unwritable config directory. That is deliberate and the caller treats it as "do not report": a per-process identifier would turn every launch into a new install and silently inflate the only number this exists to produce. Better to count nothing than to count wrongly.
Reads first and writes only when there is nothing to read, so the id is stable across launches, which is the entire point of it.
func InstallMethod ¶
func InstallMethod() string
InstallMethod guesses how this binary got here, and says "unknown" when it cannot tell.
The question it answers is which distribution channel is worth maintaining — the Homebrew tap, the Scoop bucket, the Docker image or the release tarball. Nothing in swarmcli has ever recorded it, so today that is decided on nothing.
**It is a guess from the executable's path, and deliberately conservative.** Everything it cannot place is `unknown` rather than `tarball`, even though a tarball is the likeliest answer for an unmatched path: a default that claims the most common channel would make that channel look better than it is, and the number would then be used to justify keeping it. An honest `unknown` bucket is something a reader can see and discount; a wrong `tarball` is not.
func IsFirstRun ¶
func IsFirstRun() bool
IsFirstRun reports whether no install identity has been stored yet.
Called before InstallID so the notice is shown on the run that creates the identity rather than the one after it. Any error answers false: a machine that cannot read its own config directory should not be told about telemetry it is also unable to store an identity for.
func OS ¶
func OS() string
OS and Arch are the build's, from the runtime rather than from the machine. `runtime.GOOS` is what swarmcli was compiled for, which is the thing worth knowing when deciding which builds to keep publishing.
func ShouldNotice ¶
func ShouldNotice() bool
ShouldNotice reports whether this run should show the disclosure.
True exactly once per installation: on the run that has no stored identity yet and is about to create one. A run with telemetry already switched off never shows it, because there is nothing to disclose — and showing it anyway would be an advert rather than a notice.
Types ¶
type Client ¶
type Client struct {
// URL and FallbackVersionURL are fields rather than constants so tests can
// point them at a local server.
URL string
FallbackVersionURL string
HTTP *http.Client
}
Client performs the one outbound call swarmcli makes on startup.
func (*Client) CheckIn ¶
CheckIn reports one event and returns the newest released version.
**The update check and the telemetry are one request, and that is the rule this whole change is built around.** swarmcli has always made exactly one call per launch, and adding usage reporting must not begin by doubling that: a second beacon per launch is both twice the traffic from every install and twice the surface to explain to somebody deciding whether to trust it. So the telemetry endpoint answers the version question too, and a launch stays one request whichever branch below is taken.
The two branches are the opt-out. With telemetry on, the full report goes to the telemetry endpoint. With it off, the original version check runs unchanged — the update notice is a feature the user asked for by running swarmcli, not telemetry, and switching off usage reporting must not also stop telling them a new release exists.
type Shape ¶
Shape is what kind of swarm this is, as counts.
**Counts, never names.** `docs/license.md` publishes that line for the licence requests — "how many, never which ones" — and this holds to it: a node count is a fact about scale, a node name is a map of somebody's estate. Nothing here can be turned into the second.
Pointers, so that absent and zero stay different facts. A swarm that has not been observed yet sends nothing; a swarm observed to be running no services sends `0`, and that is a real and different answer. Only `Services` can honestly be zero — a swarm always has at least the node you are asking — but all three are pointers so the next reader does not have to know which.
type State ¶
type State int
State is what the startup request does. Three states, because "no telemetry" and "no network" are different asks and conflating them served neither.
const ( // StateFull reports usage and checks for updates, in one request. The // default. // // **On by default**, which is the decision worth being explicit about // rather than burying in a boolean. What makes that defensible is the shape // of what is sent: an install identifier and a country the server derives // and the client never sees, with no address stored and nothing about the // cluster. The first-run notice says so before the first report leaves. StateFull State = iota // StateUpdateOnly sends the version-only request: no install id and nothing // about the machine, byte-identical to what shipped before usage reporting // existed. The update notice still works, because being told a new release // exists is a feature somebody asked for by running swarmcli and is not // telemetry. StateUpdateOnly // StateSilent makes no outbound request at all. The state an air-gapped or // policy-restricted cluster wants, and the one no amount of "off" could // express while this was two variables. StateSilent )
func Reporting ¶
func Reporting() State
Reporting reads the state from the environment.
Anything unrecognised leaves reporting **on**. That is the deliberate direction for a value whose absence also means on: a typo in a chart cannot silently disable it, which would be a failure nobody notices until the numbers are already wrong.