mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: add agent stats for different connection types (#6412)
This allows us to track when our extensions are used, when the web terminal is used, and average connection latency to the agent.
This commit is contained in:
Generated
+25
-5
@@ -5201,17 +5201,21 @@ const docTemplate = `{
|
||||
"agentsdk.Stats": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"conns_by_proto": {
|
||||
"connection_count": {
|
||||
"description": "ConnectionCount is the number of connections received by an agent.",
|
||||
"type": "integer"
|
||||
},
|
||||
"connection_median_latency_ms": {
|
||||
"description": "ConnectionMedianLatencyMS is the median latency of all connections in milliseconds.",
|
||||
"type": "number"
|
||||
},
|
||||
"connections_by_proto": {
|
||||
"description": "ConnectionsByProto is a count of connections by protocol.",
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"num_comms": {
|
||||
"description": "ConnectionCount is the number of connections received by an agent.",
|
||||
"type": "integer"
|
||||
},
|
||||
"rx_bytes": {
|
||||
"description": "RxBytes is the number of received bytes.",
|
||||
"type": "integer"
|
||||
@@ -5220,6 +5224,22 @@ const docTemplate = `{
|
||||
"description": "RxPackets is the number of received packets.",
|
||||
"type": "integer"
|
||||
},
|
||||
"session_count_jetbrains": {
|
||||
"description": "SessionCountJetBrains is the number of connections received by an agent\nthat are from our JetBrains extension.",
|
||||
"type": "integer"
|
||||
},
|
||||
"session_count_reconnecting_pty": {
|
||||
"description": "SessionCountReconnectingPTY is the number of connections received by an agent\nthat are from the reconnecting web terminal.",
|
||||
"type": "integer"
|
||||
},
|
||||
"session_count_ssh": {
|
||||
"description": "SessionCountSSH is the number of connections received by an agent\nthat are normal, non-tagged SSH sessions.",
|
||||
"type": "integer"
|
||||
},
|
||||
"session_count_vscode": {
|
||||
"description": "SessionCountVSCode is the number of connections received by an agent\nthat are from our VS Code extension.",
|
||||
"type": "integer"
|
||||
},
|
||||
"tx_bytes": {
|
||||
"description": "TxBytes is the number of transmitted bytes.",
|
||||
"type": "integer"
|
||||
|
||||
Generated
+25
-5
@@ -4594,17 +4594,21 @@
|
||||
"agentsdk.Stats": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"conns_by_proto": {
|
||||
"connection_count": {
|
||||
"description": "ConnectionCount is the number of connections received by an agent.",
|
||||
"type": "integer"
|
||||
},
|
||||
"connection_median_latency_ms": {
|
||||
"description": "ConnectionMedianLatencyMS is the median latency of all connections in milliseconds.",
|
||||
"type": "number"
|
||||
},
|
||||
"connections_by_proto": {
|
||||
"description": "ConnectionsByProto is a count of connections by protocol.",
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"num_comms": {
|
||||
"description": "ConnectionCount is the number of connections received by an agent.",
|
||||
"type": "integer"
|
||||
},
|
||||
"rx_bytes": {
|
||||
"description": "RxBytes is the number of received bytes.",
|
||||
"type": "integer"
|
||||
@@ -4613,6 +4617,22 @@
|
||||
"description": "RxPackets is the number of received packets.",
|
||||
"type": "integer"
|
||||
},
|
||||
"session_count_jetbrains": {
|
||||
"description": "SessionCountJetBrains is the number of connections received by an agent\nthat are from our JetBrains extension.",
|
||||
"type": "integer"
|
||||
},
|
||||
"session_count_reconnecting_pty": {
|
||||
"description": "SessionCountReconnectingPTY is the number of connections received by an agent\nthat are from the reconnecting web terminal.",
|
||||
"type": "integer"
|
||||
},
|
||||
"session_count_ssh": {
|
||||
"description": "SessionCountSSH is the number of connections received by an agent\nthat are normal, non-tagged SSH sessions.",
|
||||
"type": "integer"
|
||||
},
|
||||
"session_count_vscode": {
|
||||
"description": "SessionCountVSCode is the number of connections received by an agent\nthat are from our VS Code extension.",
|
||||
"type": "integer"
|
||||
},
|
||||
"tx_bytes": {
|
||||
"description": "TxBytes is the number of transmitted bytes.",
|
||||
"type": "integer"
|
||||
|
||||
@@ -272,18 +272,23 @@ func (q *fakeQuerier) InsertWorkspaceAgentStat(_ context.Context, p database.Ins
|
||||
defer q.mutex.Unlock()
|
||||
|
||||
stat := database.WorkspaceAgentStat{
|
||||
ID: p.ID,
|
||||
CreatedAt: p.CreatedAt,
|
||||
WorkspaceID: p.WorkspaceID,
|
||||
AgentID: p.AgentID,
|
||||
UserID: p.UserID,
|
||||
ConnectionsByProto: p.ConnectionsByProto,
|
||||
ConnectionCount: p.ConnectionCount,
|
||||
RxPackets: p.RxPackets,
|
||||
RxBytes: p.RxBytes,
|
||||
TxPackets: p.TxPackets,
|
||||
TxBytes: p.TxBytes,
|
||||
TemplateID: p.TemplateID,
|
||||
ID: p.ID,
|
||||
CreatedAt: p.CreatedAt,
|
||||
WorkspaceID: p.WorkspaceID,
|
||||
AgentID: p.AgentID,
|
||||
UserID: p.UserID,
|
||||
ConnectionsByProto: p.ConnectionsByProto,
|
||||
ConnectionCount: p.ConnectionCount,
|
||||
RxPackets: p.RxPackets,
|
||||
RxBytes: p.RxBytes,
|
||||
TxPackets: p.TxPackets,
|
||||
TxBytes: p.TxBytes,
|
||||
TemplateID: p.TemplateID,
|
||||
SessionCountVSCode: p.SessionCountVSCode,
|
||||
SessionCountJetBrains: p.SessionCountJetBrains,
|
||||
SessionCountReconnectingPTY: p.SessionCountReconnectingPTY,
|
||||
SessionCountSSH: p.SessionCountSSH,
|
||||
ConnectionMedianLatencyMS: p.ConnectionMedianLatencyMS,
|
||||
}
|
||||
q.workspaceAgentStats = append(q.workspaceAgentStats, stat)
|
||||
return stat, nil
|
||||
|
||||
Generated
+6
-1
@@ -474,7 +474,12 @@ CREATE TABLE workspace_agent_stats (
|
||||
rx_packets bigint DEFAULT 0 NOT NULL,
|
||||
rx_bytes bigint DEFAULT 0 NOT NULL,
|
||||
tx_packets bigint DEFAULT 0 NOT NULL,
|
||||
tx_bytes bigint DEFAULT 0 NOT NULL
|
||||
tx_bytes bigint DEFAULT 0 NOT NULL,
|
||||
connection_median_latency_ms bigint DEFAULT '-1'::integer NOT NULL,
|
||||
session_count_vscode bigint DEFAULT 0 NOT NULL,
|
||||
session_count_jetbrains bigint DEFAULT 0 NOT NULL,
|
||||
session_count_reconnecting_pty bigint DEFAULT 0 NOT NULL,
|
||||
session_count_ssh bigint DEFAULT 0 NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE workspace_agents (
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
ALTER TABLE workspace_agent_stats DROP COLUMN session_count_vscode,
|
||||
DROP COLUMN session_count_jetbrains,
|
||||
DROP COLUMN session_count_reconnecting_pty,
|
||||
DROP COLUMN session_count_ssh,
|
||||
DROP COLUMN connection_median_latency_ms;
|
||||
@@ -0,0 +1,5 @@
|
||||
ALTER TABLE workspace_agent_stats ADD COLUMN connection_median_latency_ms bigint DEFAULT -1 NOT NULL;
|
||||
ALTER TABLE workspace_agent_stats ADD COLUMN session_count_vscode bigint DEFAULT 0 NOT NULL;
|
||||
ALTER TABLE workspace_agent_stats ADD COLUMN session_count_jetbrains bigint DEFAULT 0 NOT NULL;
|
||||
ALTER TABLE workspace_agent_stats ADD COLUMN session_count_reconnecting_pty bigint DEFAULT 0 NOT NULL;
|
||||
ALTER TABLE workspace_agent_stats ADD COLUMN session_count_ssh bigint DEFAULT 0 NOT NULL;
|
||||
+17
-12
@@ -1549,18 +1549,23 @@ type WorkspaceAgent struct {
|
||||
}
|
||||
|
||||
type WorkspaceAgentStat struct {
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UserID uuid.UUID `db:"user_id" json:"user_id"`
|
||||
AgentID uuid.UUID `db:"agent_id" json:"agent_id"`
|
||||
WorkspaceID uuid.UUID `db:"workspace_id" json:"workspace_id"`
|
||||
TemplateID uuid.UUID `db:"template_id" json:"template_id"`
|
||||
ConnectionsByProto json.RawMessage `db:"connections_by_proto" json:"connections_by_proto"`
|
||||
ConnectionCount int64 `db:"connection_count" json:"connection_count"`
|
||||
RxPackets int64 `db:"rx_packets" json:"rx_packets"`
|
||||
RxBytes int64 `db:"rx_bytes" json:"rx_bytes"`
|
||||
TxPackets int64 `db:"tx_packets" json:"tx_packets"`
|
||||
TxBytes int64 `db:"tx_bytes" json:"tx_bytes"`
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UserID uuid.UUID `db:"user_id" json:"user_id"`
|
||||
AgentID uuid.UUID `db:"agent_id" json:"agent_id"`
|
||||
WorkspaceID uuid.UUID `db:"workspace_id" json:"workspace_id"`
|
||||
TemplateID uuid.UUID `db:"template_id" json:"template_id"`
|
||||
ConnectionsByProto json.RawMessage `db:"connections_by_proto" json:"connections_by_proto"`
|
||||
ConnectionCount int64 `db:"connection_count" json:"connection_count"`
|
||||
RxPackets int64 `db:"rx_packets" json:"rx_packets"`
|
||||
RxBytes int64 `db:"rx_bytes" json:"rx_bytes"`
|
||||
TxPackets int64 `db:"tx_packets" json:"tx_packets"`
|
||||
TxBytes int64 `db:"tx_bytes" json:"tx_bytes"`
|
||||
ConnectionMedianLatencyMS int64 `db:"connection_median_latency_ms" json:"connection_median_latency_ms"`
|
||||
SessionCountVSCode int64 `db:"session_count_vscode" json:"session_count_vscode"`
|
||||
SessionCountJetBrains int64 `db:"session_count_jetbrains" json:"session_count_jetbrains"`
|
||||
SessionCountReconnectingPTY int64 `db:"session_count_reconnecting_pty" json:"session_count_reconnecting_pty"`
|
||||
SessionCountSSH int64 `db:"session_count_ssh" json:"session_count_ssh"`
|
||||
}
|
||||
|
||||
type WorkspaceApp struct {
|
||||
|
||||
@@ -5416,25 +5416,35 @@ INSERT INTO
|
||||
rx_packets,
|
||||
rx_bytes,
|
||||
tx_packets,
|
||||
tx_bytes
|
||||
tx_bytes,
|
||||
session_count_vscode,
|
||||
session_count_jetbrains,
|
||||
session_count_reconnecting_pty,
|
||||
session_count_ssh,
|
||||
connection_median_latency_ms
|
||||
)
|
||||
VALUES
|
||||
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) RETURNING id, created_at, user_id, agent_id, workspace_id, template_id, connections_by_proto, connection_count, rx_packets, rx_bytes, tx_packets, tx_bytes
|
||||
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17) RETURNING id, created_at, user_id, agent_id, workspace_id, template_id, connections_by_proto, connection_count, rx_packets, rx_bytes, tx_packets, tx_bytes, connection_median_latency_ms, session_count_vscode, session_count_jetbrains, session_count_reconnecting_pty, session_count_ssh
|
||||
`
|
||||
|
||||
type InsertWorkspaceAgentStatParams struct {
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UserID uuid.UUID `db:"user_id" json:"user_id"`
|
||||
WorkspaceID uuid.UUID `db:"workspace_id" json:"workspace_id"`
|
||||
TemplateID uuid.UUID `db:"template_id" json:"template_id"`
|
||||
AgentID uuid.UUID `db:"agent_id" json:"agent_id"`
|
||||
ConnectionsByProto json.RawMessage `db:"connections_by_proto" json:"connections_by_proto"`
|
||||
ConnectionCount int64 `db:"connection_count" json:"connection_count"`
|
||||
RxPackets int64 `db:"rx_packets" json:"rx_packets"`
|
||||
RxBytes int64 `db:"rx_bytes" json:"rx_bytes"`
|
||||
TxPackets int64 `db:"tx_packets" json:"tx_packets"`
|
||||
TxBytes int64 `db:"tx_bytes" json:"tx_bytes"`
|
||||
ID uuid.UUID `db:"id" json:"id"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
UserID uuid.UUID `db:"user_id" json:"user_id"`
|
||||
WorkspaceID uuid.UUID `db:"workspace_id" json:"workspace_id"`
|
||||
TemplateID uuid.UUID `db:"template_id" json:"template_id"`
|
||||
AgentID uuid.UUID `db:"agent_id" json:"agent_id"`
|
||||
ConnectionsByProto json.RawMessage `db:"connections_by_proto" json:"connections_by_proto"`
|
||||
ConnectionCount int64 `db:"connection_count" json:"connection_count"`
|
||||
RxPackets int64 `db:"rx_packets" json:"rx_packets"`
|
||||
RxBytes int64 `db:"rx_bytes" json:"rx_bytes"`
|
||||
TxPackets int64 `db:"tx_packets" json:"tx_packets"`
|
||||
TxBytes int64 `db:"tx_bytes" json:"tx_bytes"`
|
||||
SessionCountVSCode int64 `db:"session_count_vscode" json:"session_count_vscode"`
|
||||
SessionCountJetBrains int64 `db:"session_count_jetbrains" json:"session_count_jetbrains"`
|
||||
SessionCountReconnectingPTY int64 `db:"session_count_reconnecting_pty" json:"session_count_reconnecting_pty"`
|
||||
SessionCountSSH int64 `db:"session_count_ssh" json:"session_count_ssh"`
|
||||
ConnectionMedianLatencyMS int64 `db:"connection_median_latency_ms" json:"connection_median_latency_ms"`
|
||||
}
|
||||
|
||||
func (q *sqlQuerier) InsertWorkspaceAgentStat(ctx context.Context, arg InsertWorkspaceAgentStatParams) (WorkspaceAgentStat, error) {
|
||||
@@ -5451,6 +5461,11 @@ func (q *sqlQuerier) InsertWorkspaceAgentStat(ctx context.Context, arg InsertWor
|
||||
arg.RxBytes,
|
||||
arg.TxPackets,
|
||||
arg.TxBytes,
|
||||
arg.SessionCountVSCode,
|
||||
arg.SessionCountJetBrains,
|
||||
arg.SessionCountReconnectingPTY,
|
||||
arg.SessionCountSSH,
|
||||
arg.ConnectionMedianLatencyMS,
|
||||
)
|
||||
var i WorkspaceAgentStat
|
||||
err := row.Scan(
|
||||
@@ -5466,6 +5481,11 @@ func (q *sqlQuerier) InsertWorkspaceAgentStat(ctx context.Context, arg InsertWor
|
||||
&i.RxBytes,
|
||||
&i.TxPackets,
|
||||
&i.TxBytes,
|
||||
&i.ConnectionMedianLatencyMS,
|
||||
&i.SessionCountVSCode,
|
||||
&i.SessionCountJetBrains,
|
||||
&i.SessionCountReconnectingPTY,
|
||||
&i.SessionCountSSH,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
@@ -12,10 +12,15 @@ INSERT INTO
|
||||
rx_packets,
|
||||
rx_bytes,
|
||||
tx_packets,
|
||||
tx_bytes
|
||||
tx_bytes,
|
||||
session_count_vscode,
|
||||
session_count_jetbrains,
|
||||
session_count_reconnecting_pty,
|
||||
session_count_ssh,
|
||||
connection_median_latency_ms
|
||||
)
|
||||
VALUES
|
||||
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) RETURNING *;
|
||||
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17) RETURNING *;
|
||||
|
||||
-- name: GetTemplateDAUs :many
|
||||
SELECT
|
||||
|
||||
@@ -25,6 +25,11 @@ overrides:
|
||||
api_key_scope_all: APIKeyScopeAll
|
||||
api_key_scope_application_connect: APIKeyScopeApplicationConnect
|
||||
avatar_url: AvatarURL
|
||||
session_count_vscode: SessionCountVSCode
|
||||
session_count_jetbrains: SessionCountJetBrains
|
||||
session_count_reconnecting_pty: SessionCountReconnectingPTY
|
||||
session_count_ssh: SessionCountSSH
|
||||
connection_median_latency_ms: ConnectionMedianLatencyMS
|
||||
login_type_oidc: LoginTypeOIDC
|
||||
oauth_access_token: OAuthAccessToken
|
||||
oauth_expiry: OAuthExpiry
|
||||
|
||||
+17
-12
@@ -941,18 +941,23 @@ func (api *API) workspaceAgentReportStats(rw http.ResponseWriter, r *http.Reques
|
||||
|
||||
now := database.Now()
|
||||
_, err = api.Database.InsertWorkspaceAgentStat(ctx, database.InsertWorkspaceAgentStatParams{
|
||||
ID: uuid.New(),
|
||||
CreatedAt: now,
|
||||
AgentID: workspaceAgent.ID,
|
||||
WorkspaceID: workspace.ID,
|
||||
UserID: workspace.OwnerID,
|
||||
TemplateID: workspace.TemplateID,
|
||||
ConnectionsByProto: payload,
|
||||
ConnectionCount: req.ConnectionCount,
|
||||
RxPackets: req.RxPackets,
|
||||
RxBytes: req.RxBytes,
|
||||
TxPackets: req.TxPackets,
|
||||
TxBytes: req.TxBytes,
|
||||
ID: uuid.New(),
|
||||
CreatedAt: now,
|
||||
AgentID: workspaceAgent.ID,
|
||||
WorkspaceID: workspace.ID,
|
||||
UserID: workspace.OwnerID,
|
||||
TemplateID: workspace.TemplateID,
|
||||
ConnectionsByProto: payload,
|
||||
ConnectionCount: req.ConnectionCount,
|
||||
RxPackets: req.RxPackets,
|
||||
RxBytes: req.RxBytes,
|
||||
TxPackets: req.TxPackets,
|
||||
TxBytes: req.TxBytes,
|
||||
SessionCountVSCode: req.SessionCountVSCode,
|
||||
SessionCountJetBrains: req.SessionCountJetBrains,
|
||||
SessionCountReconnectingPTY: req.SessionCountReconnectingPTY,
|
||||
SessionCountSSH: req.SessionCountSSH,
|
||||
ConnectionMedianLatencyMS: int64(req.ConnectionMedianLatencyMS),
|
||||
})
|
||||
if err != nil {
|
||||
httpapi.InternalServerError(rw, err)
|
||||
|
||||
@@ -1178,12 +1178,17 @@ func TestWorkspaceAgentReportStats(t *testing.T) {
|
||||
agentClient.SetSessionToken(authToken)
|
||||
|
||||
_, err := agentClient.PostStats(context.Background(), &agentsdk.Stats{
|
||||
ConnectionsByProto: map[string]int64{"TCP": 1},
|
||||
ConnectionCount: 1,
|
||||
RxPackets: 1,
|
||||
RxBytes: 1,
|
||||
TxPackets: 1,
|
||||
TxBytes: 1,
|
||||
ConnectionsByProto: map[string]int64{"TCP": 1},
|
||||
ConnectionCount: 1,
|
||||
RxPackets: 1,
|
||||
RxBytes: 1,
|
||||
TxPackets: 1,
|
||||
TxBytes: 1,
|
||||
SessionCountVSCode: 1,
|
||||
SessionCountJetBrains: 1,
|
||||
SessionCountReconnectingPTY: 1,
|
||||
SessionCountSSH: 1,
|
||||
ConnectionMedianLatencyMS: 10,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user