mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: implement boundary usage tracker and telemetry collection (#21716)
Implements telemetry for boundary usage tracking across all Coder replicas and reports them via telemetry. Changes: - Implement Tracker with Track(), FlushToDB(), and StartFlushLoop() methods - Add telemetry integration via collectBoundaryUsageSummary() - Use telemetry lock to ensure only one replica collects per period The tracker accumulates unique workspaces, unique users, and request counts (allowed/denied) in memory, then flushes to the database periodically. During telemetry collection, stats are aggregated across all replicas and reset for the next period.
This commit is contained in:
@@ -20,6 +20,7 @@ import (
|
||||
"github.com/coder/coder/v2/coderd/agentapi/metadatabatcher"
|
||||
"github.com/coder/coder/v2/coderd/agentapi/resourcesmonitor"
|
||||
"github.com/coder/coder/v2/coderd/appearance"
|
||||
"github.com/coder/coder/v2/coderd/boundaryusage"
|
||||
"github.com/coder/coder/v2/coderd/connectionlog"
|
||||
"github.com/coder/coder/v2/coderd/database"
|
||||
"github.com/coder/coder/v2/coderd/database/pubsub"
|
||||
@@ -87,6 +88,7 @@ type Options struct {
|
||||
PublishWorkspaceUpdateFn func(ctx context.Context, userID uuid.UUID, event wspubsub.WorkspaceEvent)
|
||||
PublishWorkspaceAgentLogsUpdateFn func(ctx context.Context, workspaceAgentID uuid.UUID, msg agentsdk.LogsNotifyMessage)
|
||||
NetworkTelemetryHandler func(batch []*tailnetproto.TelemetryEvent)
|
||||
BoundaryUsageTracker *boundaryusage.Tracker
|
||||
|
||||
AccessURL *url.URL
|
||||
AppHostname string
|
||||
@@ -224,10 +226,12 @@ func New(opts Options, workspace database.Workspace) *API {
|
||||
}
|
||||
|
||||
api.BoundaryLogsAPI = &BoundaryLogsAPI{
|
||||
Log: opts.Log,
|
||||
WorkspaceID: opts.WorkspaceID,
|
||||
TemplateID: workspace.TemplateID,
|
||||
TemplateVersionID: opts.TemplateVersionID,
|
||||
Log: opts.Log,
|
||||
WorkspaceID: opts.WorkspaceID,
|
||||
OwnerID: opts.OwnerID,
|
||||
TemplateID: workspace.TemplateID,
|
||||
TemplateVersionID: opts.TemplateVersionID,
|
||||
BoundaryUsageTracker: opts.BoundaryUsageTracker,
|
||||
}
|
||||
|
||||
// Start background cache refresh loop to handle workspace changes
|
||||
|
||||
@@ -8,16 +8,21 @@ import (
|
||||
|
||||
"cdr.dev/slog/v3"
|
||||
agentproto "github.com/coder/coder/v2/agent/proto"
|
||||
"github.com/coder/coder/v2/coderd/boundaryusage"
|
||||
)
|
||||
|
||||
type BoundaryLogsAPI struct {
|
||||
Log slog.Logger
|
||||
WorkspaceID uuid.UUID
|
||||
TemplateID uuid.UUID
|
||||
TemplateVersionID uuid.UUID
|
||||
Log slog.Logger
|
||||
WorkspaceID uuid.UUID
|
||||
OwnerID uuid.UUID
|
||||
TemplateID uuid.UUID
|
||||
TemplateVersionID uuid.UUID
|
||||
BoundaryUsageTracker *boundaryusage.Tracker
|
||||
}
|
||||
|
||||
func (a *BoundaryLogsAPI) ReportBoundaryLogs(ctx context.Context, req *agentproto.ReportBoundaryLogsRequest) (*agentproto.ReportBoundaryLogsResponse, error) {
|
||||
var allowed, denied int64
|
||||
|
||||
for _, l := range req.Logs {
|
||||
var logTime time.Time
|
||||
if l.Time != nil {
|
||||
@@ -32,6 +37,12 @@ func (a *BoundaryLogsAPI) ReportBoundaryLogs(ctx context.Context, req *agentprot
|
||||
continue
|
||||
}
|
||||
|
||||
if l.Allowed {
|
||||
allowed++
|
||||
} else {
|
||||
denied++
|
||||
}
|
||||
|
||||
fields := []slog.Field{
|
||||
slog.F("decision", allowBoolToString(l.Allowed)),
|
||||
slog.F("workspace_id", a.WorkspaceID.String()),
|
||||
@@ -52,6 +63,10 @@ func (a *BoundaryLogsAPI) ReportBoundaryLogs(ctx context.Context, req *agentprot
|
||||
}
|
||||
}
|
||||
|
||||
if a.BoundaryUsageTracker != nil && (allowed > 0 || denied > 0) {
|
||||
a.BoundaryUsageTracker.Track(a.WorkspaceID, a.OwnerID, allowed, denied)
|
||||
}
|
||||
|
||||
return &agentproto.ReportBoundaryLogsResponse{}, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user