feat: adds device_id, device_os, and coder_desktop_version to telemetry (#17086)

Records the Device ID, Device OS and Coder Desktop version to telemetry.

These values are provided by the Coder Desktop client in the StartRequest method of the VPN protocol. We render them as an HTTP header to transmit to Coderd, where they are decoded and added to telemetry.
This commit is contained in:
Spike Curtis
2025-03-25 15:26:05 +04:00
committed by GitHub
parent d5557fcbf5
commit 117e4c2fe7
11 changed files with 292 additions and 59 deletions

View File

@ -1652,6 +1652,8 @@ func (api *API) tailnetRPCConn(rw http.ResponseWriter, r *http.Request) {
DeviceOS: nil,
CoderDesktopVersion: nil,
}
fillCoderDesktopTelemetry(r, &connectionTelemetryEvent, api.Logger)
api.Telemetry.Report(&telemetry.Snapshot{
UserTailnetConnections: []telemetry.UserTailnetConnection{connectionTelemetryEvent},
})
@ -1681,6 +1683,34 @@ func (api *API) tailnetRPCConn(rw http.ResponseWriter, r *http.Request) {
}
}
// fillCoderDesktopTelemetry fills out the provided event based on a Coder Desktop telemetry header on the request, if
// present.
func fillCoderDesktopTelemetry(r *http.Request, event *telemetry.UserTailnetConnection, logger slog.Logger) {
// Parse desktop telemetry from header if it exists
desktopTelemetryHeader := r.Header.Get(codersdk.CoderDesktopTelemetryHeader)
if desktopTelemetryHeader != "" {
var telemetryData codersdk.CoderDesktopTelemetry
if err := telemetryData.FromHeader(desktopTelemetryHeader); err == nil {
// Only set fields if they aren't empty
if telemetryData.DeviceID != "" {
event.DeviceID = &telemetryData.DeviceID
}
if telemetryData.DeviceOS != "" {
event.DeviceOS = &telemetryData.DeviceOS
}
if telemetryData.CoderDesktopVersion != "" {
event.CoderDesktopVersion = &telemetryData.CoderDesktopVersion
}
logger.Debug(r.Context(), "received desktop telemetry",
slog.F("device_id", telemetryData.DeviceID),
slog.F("device_os", telemetryData.DeviceOS),
slog.F("desktop_version", telemetryData.CoderDesktopVersion))
} else {
logger.Warn(r.Context(), "failed to parse desktop telemetry header", slog.Error(err))
}
}
}
// createExternalAuthResponse creates an ExternalAuthResponse based on the
// provider type. This is to support legacy `/workspaceagents/me/gitauth`
// which uses `Username` and `Password`.