Documentation
¶
Overview ¶
Package analytics implements the FUS telemetry pipeline for the TeamCity CLI.
Index ¶
- Constants
- Variables
- func APIResource(endpoint string) string
- func ClassifySource(env Environment) string
- func DataDir() (string, error)
- func DetectAIAgent() string
- func DetectCI() string
- func LoadServerInfo(serverURL string) (version, serverType string)
- func NormalizeAIAgent(instillName string) string
- func NormalizeArch(goarch string) string
- func NormalizeCommand(path string) string
- func NormalizeHTTPMethod(method string) string
- func NormalizeOS(goos string) string
- func PrintFirstRunNotice(errOut io.Writer, alreadyShown, optedOut, quiet, noInput bool) bool
- func SampleEvents() []fus.LogEvent
- func SaveServerInfo(serverURL, version, serverType string) error
- func SessionFilePath() (string, error)
- type APIEvent
- type Client
- type CommandEvent
- type Config
- type Environment
- type OptOutReason
- type SchemeFinding
- type ServerInfo
- type Session
Constants ¶
const ( EventInvoked = "invoked" EventExecuted = "executed" EventLoginCompleted = "login.completed" EventLoginAbandoned = "login.abandoned" EventTokenLoaded = "token.loaded" EventStarted = "started" EventWatchFinished = "watch.finished" EventLogViewed = "log.viewed" EventTestsViewed = "tests.viewed" EventDiffViewed = "diff.viewed" EventTerminalClosed = "terminal.closed" EventExecFinished = "exec.finished" EventStateChanged = "state.changed" EventValidated = "validated" EventCreated = "created" EventSynced = "synced" EventManaged = "managed" EventLinked = "linked" )
const ( WorkspaceSourceFlag = "flag" WorkspaceSourceAuto = "auto" WorkspaceSourceInteractive = "interactive" )
const ( SourceHuman = "human" SourceAgent = "agent" SourceCI = "ci" SourceBuildStep = "build_step" )
const ( CINone = "none" CIOther = "other" CIGitHubActions = "github_actions" CIGitLab = "gitlab" CIJenkins = "jenkins" CICircleCI = "circleci" CIBuildkite = "buildkite" CIAzure = "azure" CITravis = "travis" CITeamCity = "teamcity" )
const ( AuthSourceKeyring = "keyring" AuthSourceEnv = "env" AuthSourceBuildProperties = "build_properties" AuthSourceGuest = "guest" AuthSourceNone = "none" )
const ( AuthMethodToken = "token" AuthMethodGuest = "guest" )
const ( AuthStepServer = "server" AuthStepToken = "token" AuthStepVerify = "verify" )
const ( ServerTypeCloud = "cloud" ServerTypeOnPrem = "on_prem" )
const ( ErrorAuth = "auth" ErrorPermission = "permission" ErrorNotFound = "not_found" ErrorNetwork = "network" ErrorValidation = "validation" ErrorReadOnly = "read_only" ErrorInternal = "internal" ErrorNone = "none" )
const ( BuildStatusSuccess = "success" BuildStatusFailure = "failure" BuildStatusError = "error" BuildStatusCanceled = "canceled" )
const ( LogModeFull = "full" LogModeFailed = "failed" LogModeRaw = "raw" LogModeFollow = "follow" )
const ( TestsFilterAll = "all" TestsFilterFailed = "failed" TestsFilterMuted = "muted" )
const ( AgentActionEnable = "enable" AgentActionDisable = "disable" AgentActionAuthorize = "authorize" AgentActionMove = "move" AgentActionReboot = "reboot" )
const ( AgentExitUser = "user" AgentExitTimeout = "timeout" AgentExitDisconnected = "disconnected" AgentExitError = "error" )
const ( PipelineActionPush = "push" PipelineActionPull = "pull" )
const ( SkillActionInstall = "install" SkillActionUpdate = "update" SkillActionRemove = "remove" )
const ( SkillScopeGlobal = "global" SkillScopeProject = "project" )
const ( EnvAnalytics = "TEAMCITY_ANALYTICS" EnvDoNotTrack = "DO_NOT_TRACK" )
const ( ConfigKey = "analytics" NoticeShownKey = "analytics_notice_shown" )
const ( ProductCode = "TCX" RecorderID = "TCX" RecorderVersion = 1 SchemeVersion = "1" )
const ( GroupSession = "teamcity.cli.session" GroupCommand = "teamcity.cli.command" GroupAPI = "teamcity.cli.api" GroupAuth = "teamcity.cli.auth" GroupBuild = "teamcity.cli.build" GroupAgent = "teamcity.cli.agent" GroupPipeline = "teamcity.cli.pipeline" GroupSkill = "teamcity.cli.skill" GroupWorkspace = "teamcity.cli.workspace" )
const AIAgentNone = "none"
const NoticeText = `` /* 267-byte string literal not displayed */
const Salt = "tcx-fus-v1"
Salt is the per-product anonymization namespace baked into the binary (CDN config doesn't carry one); a namespace separator, not a secret, but changing it invalidates longitudinal hash correlation.
const SessionWindow = 30 * time.Minute
Variables ¶
var Scheme = &fus.Scheme{ Version: SchemeVersion, Rules: &fus.SchemeRules{ Enums: map[string][]string{ enumBoolean: {"true", "false"}, enumOS: {"darwin", "linux", "windows", "freebsd", "other"}, enumArch: {"amd64", "arm64", "386", "other"}, enumServerType: {"cloud", "on_prem"}, enumCISystem: {"github_actions", "gitlab", "jenkins", "circleci", "buildkite", "azure", "travis", "teamcity", "other", "none"}, enumAuthSource: {"keyring", "env", "build_properties", "guest", "none"}, enumAIAgent: allAIAgents(), enumSource: {"human", "agent", "ci", "build_step"}, enumExitCode: {"0", "1", "2"}, enumErrorType: {"auth", "permission", "not_found", "network", "validation", "read_only", "internal", "none"}, enumHTTPMethod: {"GET", "POST", "PUT", "DELETE", "PATCH"}, enumAPIResource: {"builds", "build_types", "projects", "agents", "users", "vcs", "queue", "tests", "problems", "changes", "pipelines", "cloud", "server", "other"}, enumCommand: allCommands(), enumSkillAgent: skillAgentEnum(), }, Regexps: map[string]string{ regexpUUID: `[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}`, regexpSemver: `\d+\.\d+\.\d+(?:-[0-9a-zA-Z.-]+)?`, regexpServerVersion: `\d{4}\.\d{1,2}(?:\.\d+)?`, regexpInteger: `\d+`, }, }, Groups: []fus.GroupSchema{ sessionGroup(), commandGroup(), apiGroup(), authGroup(), buildGroup(), agentGroup(), pipelineGroup(), skillGroup(), workspaceGroup(), }, }
Scheme is the canonical FUS scheme; consumed at runtime and serialized to schema.json for AP registration.
Functions ¶
func APIResource ¶
APIResource maps a `/app/rest/...` endpoint to a coarse resource bucket; unknown → "other".
func ClassifySource ¶
func ClassifySource(env Environment) string
ClassifySource collapses environment context into the four-bucket source taxonomy.
func DetectAIAgent ¶
func DetectAIAgent() string
func DetectCI ¶
func DetectCI() string
DetectCI returns the wire-enum value for the surrounding CI system; teamcity wins over generic CI.
func LoadServerInfo ¶
LoadServerInfo returns the cached server version + type for serverURL; empty strings when unknown.
func NormalizeAIAgent ¶
NormalizeAIAgent maps an instill agent name to the wire enum; "" → none, unknown → other.
func NormalizeArch ¶
func NormalizeCommand ¶
NormalizeCommand returns the wire-safe value for a cobra command path; unknown → "other".
func NormalizeHTTPMethod ¶
NormalizeHTTPMethod maps an HTTP method to the wire enum; unknown → GET.
func NormalizeOS ¶
func PrintFirstRunNotice ¶
PrintFirstRunNotice writes the one-time notice; suppressed when shown, opted out, quiet, or no-input.
func SampleEvents ¶
SampleEvents returns one canonical event per (group, event_id) covering every declared field.
func SaveServerInfo ¶
SaveServerInfo writes the version + type for serverURL, merging into any existing entries.
func SessionFilePath ¶
SessionFilePath returns the persisted application-session record path.
Types ¶
type APIEvent ¶
type APIEvent struct {
Method string
Endpoint string
StatusCode int
Paginated bool
Slurp bool
HadFields bool
HadInput bool
}
APIEvent carries the api-invoked counter event; typed because raw endpoints need sanitization.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is nil-safe. Pass nil for "disabled" — every Track* method becomes a no-op.
func (*Client) Track ¶
Track emits a counter event. Field names and values must match the scheme; TestLintScheme catches drift at test time.
func (*Client) TrackCommand ¶
func (c *Client) TrackCommand(e CommandEvent)
func (*Client) TrackSession ¶
func (c *Client) TrackSession()
TrackSession emits the session.invoked state event once per new session.
type CommandEvent ¶
type CommandEvent struct {
Command string
HasJSON bool
HasGitContext bool
HasLinkContext bool
FlagCount int
ExitCode int
DurationMS int64
ErrorType string
}
CommandEvent carries the command-executed counter event; typed because exit code and error type need normalization.
type Config ¶
type Config struct {
Salt string
CLIVersion string
ServerVersion string // YYYY.MM[.x]; omitted from session event when empty
ServerType string // "cloud" | "on_prem"; omitted when empty
AuthSource string
HasLinkedProject bool
Session *Session
Environment Environment
// Debug, when non-nil, receives one line per lifecycle event (boot, track, flush). Pass f.Printer.Debug to surface only with --verbose / --debug.
Debug func(string, ...any)
}
type Environment ¶
func DetectEnvironment ¶
func DetectEnvironment() Environment
type OptOutReason ¶
type OptOutReason string
const ( OptOutNone OptOutReason = "" OptOutDoNotTrack OptOutReason = "DO_NOT_TRACK" OptOutEnv OptOutReason = "TEAMCITY_ANALYTICS=0" OptOutConfig OptOutReason = "config: analytics=false" )
func IsEnabled ¶
func IsEnabled(configEnabled bool) (bool, OptOutReason)
IsEnabled reports whether analytics tracking is on; precedence: DO_NOT_TRACK > TEAMCITY_ANALYTICS > config > on.
type SchemeFinding ¶
type SchemeFinding struct {
Group string
Event string
Field string // empty when the diagnostic is on event.id
Got string // a "validation.*" sentinel
}
SchemeFinding is a single client-side-validation diagnostic against a sample event.
func LintScheme ¶
func LintScheme() ([]SchemeFinding, error)
LintScheme runs every SampleEvents entry through the Scheme validator and returns any sentinels emitted.
func (SchemeFinding) String ¶
func (f SchemeFinding) String() string
type ServerInfo ¶
type ServerInfo struct {
Version string `json:"version,omitempty"`
Type string `json:"type,omitempty"`
}
ServerInfo is the telemetry-only cache of TC server context, keyed by server URL. Lives alongside the FUS buffer in DataDir so users can wipe all telemetry state in one shot.