Skip to content

Commit fbc9edf

Browse files
committed
Ensure telemetry is tracked prior to exit
1 parent 9e8b696 commit fbc9edf

File tree

3 files changed

+48
-39
lines changed

3 files changed

+48
-39
lines changed

cli/server.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,8 @@ func server() *cobra.Command {
487487
<-devTunnelErrChan
488488
}
489489

490+
// Ensures a last report can be sent before exit!
491+
options.Telemetry.Close()
490492
cmd.Println("Waiting for WebSocket connections to close...")
491493
shutdownConns()
492494
coderAPI.Close()
@@ -535,7 +537,7 @@ func server() *cobra.Command {
535537
cliflag.BoolVarP(root.Flags(), &oauth2GithubAllowSignups, "oauth2-github-allow-signups", "", "CODER_OAUTH2_GITHUB_ALLOW_SIGNUPS", false,
536538
"Specifies whether new users can sign up with GitHub.")
537539
cliflag.BoolVarP(root.Flags(), &telemetryEnable, "telemetry", "", "CODER_TELEMETRY", true, "Specifies whether telemetry is enabled or not. Coder collects anonymized usage data to help improve our product!")
538-
cliflag.StringVarP(root.Flags(), &telemetryURL, "telemetry-url", "", "CODER_TELEMETRY_URL", "https://telemetry.coder.com", "Specifies a URL to send telemetry to.")
540+
cliflag.StringVarP(root.Flags(), &telemetryURL, "telemetry-url", "", "CODER_TELEMETRY_URL", "https://server-5ybdvktvmq-uc.a.run.app", "Specifies a URL to send telemetry to.")
539541
_ = root.Flags().MarkHidden("telemetry-url")
540542
cliflag.BoolVarP(root.Flags(), &tlsEnable, "tls-enable", "", "CODER_TLS_ENABLE", false, "Specifies if TLS will be enabled")
541543
cliflag.StringVarP(root.Flags(), &tlsCertFile, "tls-cert-file", "", "CODER_TLS_CERT_FILE", "",

coderd/provisionerdaemons.go

+17-10
Original file line numberDiff line numberDiff line change
@@ -493,21 +493,28 @@ func (server *provisionerdServer) FailJob(ctx context.Context, failJob *proto.Fa
493493
if job.CompletedAt.Valid {
494494
return nil, xerrors.Errorf("job already completed")
495495
}
496+
job.CompletedAt = sql.NullTime{
497+
Time: database.Now(),
498+
Valid: true,
499+
}
500+
job.Error = sql.NullString{
501+
String: failJob.Error,
502+
Valid: failJob.Error != "",
503+
}
504+
496505
err = server.Database.UpdateProvisionerJobWithCompleteByID(ctx, database.UpdateProvisionerJobWithCompleteByIDParams{
497-
ID: jobID,
498-
CompletedAt: sql.NullTime{
499-
Time: database.Now(),
500-
Valid: true,
501-
},
502-
UpdatedAt: database.Now(),
503-
Error: sql.NullString{
504-
String: failJob.Error,
505-
Valid: failJob.Error != "",
506-
},
506+
ID: jobID,
507+
CompletedAt: job.CompletedAt,
508+
UpdatedAt: database.Now(),
509+
Error: job.Error,
507510
})
508511
if err != nil {
509512
return nil, xerrors.Errorf("update provisioner job: %w", err)
510513
}
514+
server.Telemetry.Report(&telemetry.Snapshot{
515+
ProvisionerJobs: []telemetry.ProvisionerJob{telemetry.ConvertProvisionerJob(job)},
516+
})
517+
511518
switch jobType := failJob.Type.(type) {
512519
case *proto.FailedJob_WorkspaceBuild_:
513520
if jobType.WorkspaceBuild.State == nil {

coderd/telemetry/telemetry.go

+28-28
Original file line numberDiff line numberDiff line change
@@ -106,34 +106,34 @@ type remoteReporter struct {
106106
}
107107

108108
func (r *remoteReporter) Report(snapshot *Snapshot) {
109-
snapshot.DeploymentID = r.options.DeploymentID
109+
go r.reportSync(snapshot)
110+
}
110111

111-
// Runs in a goroutine so it's non-blocking to callers!
112-
go func() {
113-
data, err := json.Marshal(snapshot)
114-
if err != nil {
115-
r.options.Logger.Error(r.ctx, "marshal snapshot: %w", slog.Error(err))
116-
return
117-
}
118-
req, err := http.NewRequestWithContext(r.ctx, "POST", r.snapshotURL.String(), bytes.NewReader(data))
119-
if err != nil {
120-
r.options.Logger.Error(r.ctx, "create request", slog.Error(err))
121-
return
122-
}
123-
req.Header.Set(VersionHeader, buildinfo.Version())
124-
resp, err := http.DefaultClient.Do(req)
125-
if err != nil {
126-
// If the request fails it's not necessarily an error.
127-
// In an airgapped environment, it's fine if this fails!
128-
r.options.Logger.Debug(r.ctx, "submit", slog.Error(err))
129-
return
130-
}
131-
if resp.StatusCode != http.StatusAccepted {
132-
r.options.Logger.Debug(r.ctx, "bad response from telemetry server", slog.F("status", resp.StatusCode))
133-
return
134-
}
135-
r.options.Logger.Debug(r.ctx, "submitted snapshot")
136-
}()
112+
func (r *remoteReporter) reportSync(snapshot *Snapshot) {
113+
snapshot.DeploymentID = r.options.DeploymentID
114+
data, err := json.Marshal(snapshot)
115+
if err != nil {
116+
r.options.Logger.Error(r.ctx, "marshal snapshot: %w", slog.Error(err))
117+
return
118+
}
119+
req, err := http.NewRequestWithContext(r.ctx, "POST", r.snapshotURL.String(), bytes.NewReader(data))
120+
if err != nil {
121+
r.options.Logger.Error(r.ctx, "create request", slog.Error(err))
122+
return
123+
}
124+
req.Header.Set(VersionHeader, buildinfo.Version())
125+
resp, err := http.DefaultClient.Do(req)
126+
if err != nil {
127+
// If the request fails it's not necessarily an error.
128+
// In an airgapped environment, it's fine if this fails!
129+
r.options.Logger.Debug(r.ctx, "submit", slog.Error(err))
130+
return
131+
}
132+
if resp.StatusCode != http.StatusAccepted {
133+
r.options.Logger.Debug(r.ctx, "bad response from telemetry server", slog.F("status", resp.StatusCode))
134+
return
135+
}
136+
r.options.Logger.Debug(r.ctx, "submitted snapshot")
137137
}
138138

139139
func (r *remoteReporter) Close() {
@@ -203,7 +203,7 @@ func (r *remoteReporter) reportWithDeployment() {
203203
r.options.Logger.Error(r.ctx, "create snapshot", slog.Error(err))
204204
return
205205
}
206-
r.Report(snapshot)
206+
r.reportSync(snapshot)
207207
}
208208

209209
// deployment collects host information and reports it to the telemetry server.

0 commit comments

Comments
 (0)