diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 8c765a3e9b2b5..a07c9a8fc4b97 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -9916,6 +9916,10 @@ const docTemplate = `{ "codersdk.UserLatency": { "type": "object", "properties": { + "avatar_url": { + "type": "string", + "format": "uri" + }, "latency_ms": { "$ref": "#/definitions/codersdk.ConnectionLatency" }, diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index 2dc5fedea55ea..47fbbca0234bb 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -8966,6 +8966,10 @@ "codersdk.UserLatency": { "type": "object", "properties": { + "avatar_url": { + "type": "string", + "format": "uri" + }, "latency_ms": { "$ref": "#/definitions/codersdk.ConnectionLatency" }, diff --git a/coderd/database/dbfake/dbfake.go b/coderd/database/dbfake/dbfake.go index 7bfaa6aa29246..bb9b7235939b0 100644 --- a/coderd/database/dbfake/dbfake.go +++ b/coderd/database/dbfake/dbfake.go @@ -2369,6 +2369,7 @@ func (q *FakeQuerier) GetUserLatencyInsights(_ context.Context, arg database.Get row := database.GetUserLatencyInsightsRow{ UserID: userID, Username: user.Username, + AvatarURL: user.AvatarURL, TemplateIDs: templateIDs, WorkspaceConnectionLatency50: tryPercentile(latencies, 50), WorkspaceConnectionLatency95: tryPercentile(latencies, 95), diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go index 120edc4eb949c..920f488b1e915 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -1545,6 +1545,7 @@ const getUserLatencyInsights = `-- name: GetUserLatencyInsights :many SELECT workspace_agent_stats.user_id, users.username, + users.avatar_url, array_agg(DISTINCT template_id)::uuid[] AS template_ids, coalesce((PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY connection_median_latency_ms)), -1)::FLOAT AS workspace_connection_latency_50, coalesce((PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY connection_median_latency_ms)), -1)::FLOAT AS workspace_connection_latency_95 @@ -1556,7 +1557,7 @@ WHERE AND workspace_agent_stats.connection_median_latency_ms > 0 AND workspace_agent_stats.connection_count > 0 AND CASE WHEN COALESCE(array_length($3::uuid[], 1), 0) > 0 THEN template_id = ANY($3::uuid[]) ELSE TRUE END -GROUP BY workspace_agent_stats.user_id, users.username +GROUP BY workspace_agent_stats.user_id, users.username, users.avatar_url ORDER BY user_id ASC ` @@ -1567,11 +1568,12 @@ type GetUserLatencyInsightsParams struct { } type GetUserLatencyInsightsRow struct { - UserID uuid.UUID `db:"user_id" json:"user_id"` - Username string `db:"username" json:"username"` - TemplateIDs []uuid.UUID `db:"template_ids" json:"template_ids"` - WorkspaceConnectionLatency50 float64 `db:"workspace_connection_latency_50" json:"workspace_connection_latency_50"` - WorkspaceConnectionLatency95 float64 `db:"workspace_connection_latency_95" json:"workspace_connection_latency_95"` + UserID uuid.UUID `db:"user_id" json:"user_id"` + Username string `db:"username" json:"username"` + AvatarURL sql.NullString `db:"avatar_url" json:"avatar_url"` + TemplateIDs []uuid.UUID `db:"template_ids" json:"template_ids"` + WorkspaceConnectionLatency50 float64 `db:"workspace_connection_latency_50" json:"workspace_connection_latency_50"` + WorkspaceConnectionLatency95 float64 `db:"workspace_connection_latency_95" json:"workspace_connection_latency_95"` } // GetUserLatencyInsights returns the median and 95th percentile connection @@ -1590,6 +1592,7 @@ func (q *sqlQuerier) GetUserLatencyInsights(ctx context.Context, arg GetUserLate if err := rows.Scan( &i.UserID, &i.Username, + &i.AvatarURL, pq.Array(&i.TemplateIDs), &i.WorkspaceConnectionLatency50, &i.WorkspaceConnectionLatency95, diff --git a/coderd/database/queries/insights.sql b/coderd/database/queries/insights.sql index e611ab209ff68..d24128fc31f48 100644 --- a/coderd/database/queries/insights.sql +++ b/coderd/database/queries/insights.sql @@ -6,6 +6,7 @@ SELECT workspace_agent_stats.user_id, users.username, + users.avatar_url, array_agg(DISTINCT template_id)::uuid[] AS template_ids, coalesce((PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY connection_median_latency_ms)), -1)::FLOAT AS workspace_connection_latency_50, coalesce((PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY connection_median_latency_ms)), -1)::FLOAT AS workspace_connection_latency_95 @@ -17,7 +18,7 @@ WHERE AND workspace_agent_stats.connection_median_latency_ms > 0 AND workspace_agent_stats.connection_count > 0 AND CASE WHEN COALESCE(array_length(@template_ids::uuid[], 1), 0) > 0 THEN template_id = ANY(@template_ids::uuid[]) ELSE TRUE END -GROUP BY workspace_agent_stats.user_id, users.username +GROUP BY workspace_agent_stats.user_id, users.username, users.avatar_url ORDER BY user_id ASC; -- name: GetTemplateInsights :one diff --git a/coderd/insights.go b/coderd/insights.go index 3da60a13bfe84..f5f5b4ab2fd19 100644 --- a/coderd/insights.go +++ b/coderd/insights.go @@ -117,6 +117,7 @@ func (api *API) insightsUserLatency(rw http.ResponseWriter, r *http.Request) { TemplateIDs: row.TemplateIDs, UserID: row.UserID, Username: row.Username, + AvatarURL: row.AvatarURL.String, LatencyMS: codersdk.ConnectionLatency{ P50: row.WorkspaceConnectionLatency50, P95: row.WorkspaceConnectionLatency95, diff --git a/codersdk/insights.go b/codersdk/insights.go index fb1c582c686c8..f746e5c1243d8 100644 --- a/codersdk/insights.go +++ b/codersdk/insights.go @@ -44,6 +44,7 @@ type UserLatency struct { TemplateIDs []uuid.UUID `json:"template_ids" format:"uuid"` UserID uuid.UUID `json:"user_id" format:"uuid"` Username string `json:"username"` + AvatarURL string `json:"avatar_url" format:"uri"` LatencyMS ConnectionLatency `json:"latency_ms"` } diff --git a/docs/api/insights.md b/docs/api/insights.md index a802916fa579c..f3ceaffea13db 100644 --- a/docs/api/insights.md +++ b/docs/api/insights.md @@ -117,6 +117,7 @@ curl -X GET http://coder-server:8080/api/v2/insights/user-latency \ "template_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"], "users": [ { + "avatar_url": "http://example.com", "latency_ms": { "p50": 31.312, "p95": 119.832 diff --git a/docs/api/schemas.md b/docs/api/schemas.md index a8cee1c174fce..a5958e7e92a26 100644 --- a/docs/api/schemas.md +++ b/docs/api/schemas.md @@ -4879,6 +4879,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| ```json { + "avatar_url": "http://example.com", "latency_ms": { "p50": 31.312, "p95": 119.832 @@ -4893,6 +4894,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| | Name | Type | Required | Restrictions | Description | | -------------- | -------------------------------------------------------- | -------- | ------------ | ----------- | +| `avatar_url` | string | false | | | | `latency_ms` | [codersdk.ConnectionLatency](#codersdkconnectionlatency) | false | | | | `template_ids` | array of string | false | | | | `user_id` | string | false | | | @@ -4907,6 +4909,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| "template_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"], "users": [ { + "avatar_url": "http://example.com", "latency_ms": { "p50": 31.312, "p95": 119.832 @@ -4938,6 +4941,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| "template_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"], "users": [ { + "avatar_url": "http://example.com", "latency_ms": { "p50": 31.312, "p95": 119.832 diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 4bc840801994e..5714b39fef7ba 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -1176,6 +1176,7 @@ export interface UserLatency { readonly template_ids: string[] readonly user_id: string readonly username: string + readonly avatar_url: string readonly latency_ms: ConnectionLatency }