diff --git a/cli/server.go b/cli/server.go index b6c51e9812..acb3f3b4f2 100644 --- a/cli/server.go +++ b/cli/server.go @@ -509,18 +509,28 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co return xerrors.Errorf("parse telemetry url: %w", err) } + gitAuth := make([]telemetry.GitAuth, 0) + for _, cfg := range gitAuthConfigs { + gitAuth = append(gitAuth, telemetry.GitAuth{ + Type: string(cfg.Type), + }) + } + options.Telemetry, err = telemetry.New(telemetry.Options{ - BuiltinPostgres: builtinPostgres, - DeploymentID: deploymentID, - Database: options.Database, - Logger: logger.Named("telemetry"), - URL: telemetryURL, - GitHubOAuth: cfg.OAuth2.Github.ClientID.Value != "", - OIDCAuth: cfg.OIDC.ClientID.Value != "", - OIDCIssuerURL: cfg.OIDC.IssuerURL.Value, - Prometheus: cfg.Prometheus.Enable.Value, - STUN: len(cfg.DERP.Server.STUNAddresses.Value) != 0, - Tunnel: tunnel != nil, + BuiltinPostgres: builtinPostgres, + DeploymentID: deploymentID, + Database: options.Database, + Logger: logger.Named("telemetry"), + URL: telemetryURL, + Wildcard: cfg.WildcardAccessURL.Value != "", + DERPServerRelayURL: cfg.DERP.Server.RelayURL.Value, + GitAuth: gitAuth, + GitHubOAuth: cfg.OAuth2.Github.ClientID.Value != "", + OIDCAuth: cfg.OIDC.ClientID.Value != "", + OIDCIssuerURL: cfg.OIDC.IssuerURL.Value, + Prometheus: cfg.Prometheus.Enable.Value, + STUN: len(cfg.DERP.Server.STUNAddresses.Value) != 0, + Tunnel: tunnel != nil, }) if err != nil { return xerrors.Errorf("create telemetry reporter: %w", err) diff --git a/coderd/telemetry/telemetry.go b/coderd/telemetry/telemetry.go index 0fce2b7f8f..e63ebe47d2 100644 --- a/coderd/telemetry/telemetry.go +++ b/coderd/telemetry/telemetry.go @@ -39,15 +39,18 @@ type Options struct { // URL is an endpoint to direct telemetry towards! URL *url.URL - BuiltinPostgres bool - DeploymentID string - GitHubOAuth bool - OIDCAuth bool - OIDCIssuerURL string - Prometheus bool - STUN bool - SnapshotFrequency time.Duration - Tunnel bool + BuiltinPostgres bool + DeploymentID string + GitHubOAuth bool + OIDCAuth bool + OIDCIssuerURL string + Wildcard bool + DERPServerRelayURL string + GitAuth []GitAuth + Prometheus bool + STUN bool + SnapshotFrequency time.Duration + Tunnel bool } // New constructs a reporter for telemetry data. @@ -228,27 +231,30 @@ func (r *remoteReporter) deployment() error { containerized = *sysInfo.Containerized } data, err := json.Marshal(&Deployment{ - ID: r.options.DeploymentID, - Architecture: sysInfo.Architecture, - BuiltinPostgres: r.options.BuiltinPostgres, - Containerized: containerized, - Kubernetes: os.Getenv("KUBERNETES_SERVICE_HOST") != "", - GitHubOAuth: r.options.GitHubOAuth, - OIDCAuth: r.options.OIDCAuth, - OIDCIssuerURL: r.options.OIDCIssuerURL, - Prometheus: r.options.Prometheus, - STUN: r.options.STUN, - Tunnel: r.options.Tunnel, - OSType: sysInfo.OS.Type, - OSFamily: sysInfo.OS.Family, - OSPlatform: sysInfo.OS.Platform, - OSName: sysInfo.OS.Name, - OSVersion: sysInfo.OS.Version, - CPUCores: runtime.NumCPU(), - MemoryTotal: mem.Total, - MachineID: sysInfo.UniqueID, - StartedAt: r.startedAt, - ShutdownAt: r.shutdownAt, + ID: r.options.DeploymentID, + Architecture: sysInfo.Architecture, + BuiltinPostgres: r.options.BuiltinPostgres, + Containerized: containerized, + Wildcard: r.options.Wildcard, + DERPServerRelayURL: r.options.DERPServerRelayURL, + GitAuth: r.options.GitAuth, + Kubernetes: os.Getenv("KUBERNETES_SERVICE_HOST") != "", + GitHubOAuth: r.options.GitHubOAuth, + OIDCAuth: r.options.OIDCAuth, + OIDCIssuerURL: r.options.OIDCIssuerURL, + Prometheus: r.options.Prometheus, + STUN: r.options.STUN, + Tunnel: r.options.Tunnel, + OSType: sysInfo.OS.Type, + OSFamily: sysInfo.OS.Family, + OSPlatform: sysInfo.OS.Platform, + OSName: sysInfo.OS.Name, + OSVersion: sysInfo.OS.Version, + CPUCores: runtime.NumCPU(), + MemoryTotal: mem.Total, + MachineID: sysInfo.UniqueID, + StartedAt: r.startedAt, + ShutdownAt: r.shutdownAt, }) if err != nil { return xerrors.Errorf("marshal deployment: %w", err) @@ -512,17 +518,28 @@ func ConvertProvisionerJob(job database.ProvisionerJob) ProvisionerJob { // ConvertWorkspaceAgent anonymizes a workspace agent. func ConvertWorkspaceAgent(agent database.WorkspaceAgent) WorkspaceAgent { - return WorkspaceAgent{ - ID: agent.ID, - CreatedAt: agent.CreatedAt, - ResourceID: agent.ResourceID, - InstanceAuth: agent.AuthInstanceID.Valid, - Architecture: agent.Architecture, - OperatingSystem: agent.OperatingSystem, - EnvironmentVariables: agent.EnvironmentVariables.Valid, - StartupScript: agent.StartupScript.Valid, - Directory: agent.Directory != "", + snapAgent := WorkspaceAgent{ + ID: agent.ID, + CreatedAt: agent.CreatedAt, + ResourceID: agent.ResourceID, + InstanceAuth: agent.AuthInstanceID.Valid, + Architecture: agent.Architecture, + OperatingSystem: agent.OperatingSystem, + EnvironmentVariables: agent.EnvironmentVariables.Valid, + StartupScript: agent.StartupScript.Valid, + Directory: agent.Directory != "", + ConnectionTimeoutSeconds: agent.ConnectionTimeoutSeconds, } + if agent.FirstConnectedAt.Valid { + snapAgent.FirstConnectedAt = &agent.FirstConnectedAt.Time + } + if agent.LastConnectedAt.Valid { + snapAgent.LastConnectedAt = &agent.LastConnectedAt.Time + } + if agent.DisconnectedAt.Valid { + snapAgent.DisconnectedAt = &agent.DisconnectedAt.Time + } + return snapAgent } // ConvertWorkspaceApp anonymizes a workspace app. @@ -625,27 +642,34 @@ type Snapshot struct { // Deployment contains information about the host running Coder. type Deployment struct { - ID string `json:"id"` - Architecture string `json:"architecture"` - BuiltinPostgres bool `json:"builtin_postgres"` - Containerized bool `json:"containerized"` - Kubernetes bool `json:"kubernetes"` - Tunnel bool `json:"tunnel"` - GitHubOAuth bool `json:"github_oauth"` - OIDCAuth bool `json:"oidc_auth"` - OIDCIssuerURL string `json:"oidc_issuer_url"` - Prometheus bool `json:"prometheus"` - STUN bool `json:"stun"` - OSType string `json:"os_type"` - OSFamily string `json:"os_family"` - OSPlatform string `json:"os_platform"` - OSName string `json:"os_name"` - OSVersion string `json:"os_version"` - CPUCores int `json:"cpu_cores"` - MemoryTotal uint64 `json:"memory_total"` - MachineID string `json:"machine_id"` - StartedAt time.Time `json:"started_at"` - ShutdownAt *time.Time `json:"shutdown_at"` + ID string `json:"id"` + Architecture string `json:"architecture"` + BuiltinPostgres bool `json:"builtin_postgres"` + Containerized bool `json:"containerized"` + Kubernetes bool `json:"kubernetes"` + Tunnel bool `json:"tunnel"` + Wildcard bool `json:"wildcard"` + DERPServerRelayURL string `json:"derp_server_relay_url"` + GitAuth []GitAuth `json:"git_auth"` + GitHubOAuth bool `json:"github_oauth"` + OIDCAuth bool `json:"oidc_auth"` + OIDCIssuerURL string `json:"oidc_issuer_url"` + Prometheus bool `json:"prometheus"` + STUN bool `json:"stun"` + OSType string `json:"os_type"` + OSFamily string `json:"os_family"` + OSPlatform string `json:"os_platform"` + OSName string `json:"os_name"` + OSVersion string `json:"os_version"` + CPUCores int `json:"cpu_cores"` + MemoryTotal uint64 `json:"memory_total"` + MachineID string `json:"machine_id"` + StartedAt time.Time `json:"started_at"` + ShutdownAt *time.Time `json:"shutdown_at"` +} + +type GitAuth struct { + Type string `json:"type"` } type APIKey struct { @@ -682,15 +706,19 @@ type WorkspaceResourceMetadata struct { } type WorkspaceAgent struct { - ID uuid.UUID `json:"id"` - CreatedAt time.Time `json:"created_at"` - ResourceID uuid.UUID `json:"resource_id"` - InstanceAuth bool `json:"instance_auth"` - Architecture string `json:"architecture"` - OperatingSystem string `json:"operating_system"` - EnvironmentVariables bool `json:"environment_variables"` - StartupScript bool `json:"startup_script"` - Directory bool `json:"directory"` + ID uuid.UUID `json:"id"` + CreatedAt time.Time `json:"created_at"` + ResourceID uuid.UUID `json:"resource_id"` + InstanceAuth bool `json:"instance_auth"` + Architecture string `json:"architecture"` + OperatingSystem string `json:"operating_system"` + EnvironmentVariables bool `json:"environment_variables"` + StartupScript bool `json:"startup_script"` + Directory bool `json:"directory"` + FirstConnectedAt *time.Time `json:"first_connected_at"` + LastConnectedAt *time.Time `json:"last_connected_at"` + DisconnectedAt *time.Time `json:"disconnected_at"` + ConnectionTimeoutSeconds int32 `json:"connection_timeout_seconds"` } type WorkspaceApp struct {