{{define "dashboard"}} llmgw — cluster

Cluster

{{.NodeCount}} nodes · {{.ReadyReplicas}} of {{.TotalReplicas}} replicas ready · {{.ModelCount}} models

{{if .HasCharts}}
{{.Requests24h}}
requests · 24h
{{.RequestSpark}}
{{compact .Tokens24h}}
tokens · 24h
{{.TokenSpark}}
{{.Errors24h}}
errors · 24h
{{units .Spend24h}}
spend · 24h
{{end}}

Capacity

{{if .Summary.GPUs}} {{range .Summary.GPUs}}{{end}}
ClassIn useFreeFaultyUsage
{{.Class}} {{.Used}}/{{.Total}} {{.Free}} {{if .Unhealthy}}{{.Unhealthy}}{{else}}—{{end}} {{pct .Used .Total}}%
{{else}}

No GPUs have been reported.

{{end}} {{if .Summary.Fabrics}}

Fabrics

{{range .Summary.Fabrics}}{{end}}
FabricNodesFully freeWeights
{{.Fabric}} {{.Nodes}} {{.LargestFreeBlock}} {{if .NodesWithWeights}}{{.Models}} model(s) on {{.NodesWithWeights}}/{{.Nodes}} nodes{{else}}not reported{{end}}

Fully free counts whole unused nodes, which is what decides whether a replica spanning nodes can land: free cards on the wrong fabric are not capacity for a model that needs this one.

{{end}} {{if .Summary.IdleReplicas}}

Holding hardware nothing is asking for

{{range .Summary.IdleReplicas}}{{end}}
ReplicaModelGPUsUnused for
{{.ID}} {{.Model}} {{.GPUs}} {{duration .IdleSec}}
{{end}} {{if .HasPeople}}

People

{{.UserChart}} {{range .Users}}{{end}}
PersonKeysRequestsTokensErrorsSpendLast seen
{{if .Email}}{{.Email}}{{else}}operator-issued keys{{end}} {{.Keys}} {{.Requests}} {{compact .Tokens}} {{if .Errors}}{{.Errors}}{{else}}—{{end}} {{units .CostMicros}} {{ago .LastSeen}}
{{end}} {{if .Models2}}

What is being run

{{.ModelChart}} {{range .Models2}}{{end}}
ModelRequestsTokensErrorsMean latency
{{.Model}} {{.Requests}} {{compact .Tokens}} {{if .Errors}}{{.Errors}}{{else}}—{{end}} {{printf "%.0f" .AvgLatency}} ms

Counted by the model that actually answered, which differs from the one requested whenever a fallback served it.

{{end}}

Nodes

{{if .Nodes}} {{range .Nodes}} {{/* Free out of total, because the first is meaningless without the second, and an em dash where nothing was reported: an agent that was never asked about its disk must not read as a full one. */}} {{if .Unhealthy}}{{end}} {{end}}
NodeStateGPUsRAMDiskClassesFabricsModelsReplicasLast seen
{{.ID}}{{if .MgmtAddr}} {{.MgmtAddr}}{{end}} {{.State}} {{.GPUFree}}/{{.GPUTotal}} {{if .MemoryGB}}{{.MemoryGB}}G{{else}}—{{end}}{{if .DiskTotalGB}}{{.DiskFreeGB}}G/{{.DiskTotalGB}}G{{else}}—{{end}} {{join .Classes}} {{join .Fabrics}} {{if .Models}}{{len .Models}}{{else}}—{{end}} {{.Replicas}} {{or .LastSeenAgo "—"}}
{{join .Unhealthy}}
{{else}}

No agents have registered.

{{end}}

Models

{{if .Models}} {{range .Models}}{{end}}
ModelAliasesReadyWantedProfilesFallbacks
{{.Name}} {{join .Aliases}} {{.Ready}} {{.Min}}–{{.Max}} {{join .Profiles}} {{join .Fallbacks}}
{{else}}

The catalog is empty.

{{end}} {{if .Unplaced}}

Why nothing was placed

{{range .Unplaced}}

{{.Model}}

{{range .Rejections}}{{.Profile}} @ {{or .Pool "-"}}{{if .Node}}/{{.Node}}{{end}}: {{.Reason}}
{{end}}
{{end}} {{end}}

Replicas

{{if .Replicas}} {{range .Replicas}}{{if .Err}}{{end}} {{end}}
ReplicaModelStatePoolEndpointAgeNodes
{{.ID}} {{.Model}} {{.State}} {{or .Pool "—"}} {{if .Endpoint}}{{.Endpoint}}{{else}}—{{end}} {{duration .AgeSec}} {{range .Shards}}{{.Node}} {{end}}
{{.Err}}
{{else}}

No replicas.

{{end}}

Traffic — last 24 hours, hourly

{{if .HasCharts}}

Requests

{{.RequestChart}}

Tokens

{{.TokenChart}}

Mean latency

{{.LatencyChart}}
{{else if .AuthEnabled}}

No traffic recorded yet.

{{end}}

Usage — last 24 hours

{{if .AuthEnabled}} {{if .Usage}} {{range .Usage}}{{end}}
KeyProjectRequestsErrorsPromptCompletionSpendLast
{{if .KeyName}}{{.KeyName}} {{.KeyPrefix}}{{else}}{{.KeyID}}{{end}} {{.ProjectID}} {{.Requests}} {{if .Errors}}{{.Errors}}{{else}}0{{end}} {{.Prompt}} {{.Completion}} {{units .CostMicros}} {{ago .LastAt}}

Spend is in units, whatever a unit was configured to mean. Usage is written in batches, so the last few seconds may be missing.

{{else}}

No requests recorded in the last 24 hours.

{{end}} {{else}}

Authentication is off, so there is no identity to account against.

{{end}} {{if not .OnAdminListener}}

Metrics, pprof and the management API are on the admin listener, which is bound to loopback and not reachable from here. pprof can dump the process heap, where API keys sit in plaintext, which is why that port is not exposed: ssh -L 9090:127.0.0.1:9090 <control-plane>

{{end}}
{{end}}