thanos

package
v0.9.10 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 17, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package thanos implements a read-only client for the Thanos Querier endpoints of external OpenShift clusters (v0.8.575, audit: docs/audit/thanos-multicluster-metrics-audit.md). It powers the /clusters surface: per-(namespace, pod) CPU + memory pulled straight from each cluster's platform monitoring stack — telemetry the applications themselves never emit.

Structure mirrors internal/tempo/client.go (the canonical external-query-service template): typed Settings blob in system_settings under "thanos_clusters", narrow settingsStore interface, LoadPersisted at boot + StartConfigRefresh 30s poll for multi-pod sync, SavePersisted + live Configure swap, and a masked Snapshot for the settings UI. The one structural difference: Settings holds a LIST of clusters, and TLS-verify varies per cluster — so instead of tempo's rebuild-on-toggle single client, this package uses the Zoom two-singleton pattern (notify.go:1106): one verifying client + one lazily-built insecure twin, picked per request via thanosClientFor.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ClusterConfig

type ClusterConfig struct {
	Name string `json:"name"`
	URL  string `json:"url"`
	// AuthType — none | bearer. Bearer covers the standard
	// OpenShift path: a ServiceAccount token with the
	// cluster-monitoring-view ClusterRole against the
	// oauth-proxy'd thanos-querier route.
	AuthType string `json:"authType,omitempty"`
	// Token — never echoed; Snapshot exposes HasToken only.
	Token string `json:"token,omitempty"`
	// NamespaceFilter is a PromQL regex injected as
	// namespace=~"..." into every query — the cardinality shield
	// that keeps a 10k-pod estate from riding home in one
	// response. Empty = all namespaces (topk still caps rows).
	NamespaceFilter    string `json:"namespaceFilter,omitempty"`
	InsecureSkipVerify bool   `json:"insecureSkipVerify,omitempty"`
	Enabled            bool   `json:"enabled"`
}

ClusterConfig is one remote cluster entry. Name doubles as the APM join key: it must equal the cluster value spans carry (k8s.cluster.name / openshift.cluster.name — clusterDeriveExpr) for the service→cluster pivot to light up; the Settings UI suggests observed names for exactly that reason.

type ClusterSnapshot

type ClusterSnapshot struct {
	Name               string `json:"name"`
	URL                string `json:"url"`
	AuthType           string `json:"authType,omitempty"`
	HasToken           bool   `json:"hasToken"`
	NamespaceFilter    string `json:"namespaceFilter,omitempty"`
	InsecureSkipVerify bool   `json:"insecureSkipVerify,omitempty"`
	Enabled            bool   `json:"enabled"`
}

ClusterSnapshot mirrors ClusterConfig with the token masked.

type ClusterSummary added in v0.8.586

type ClusterSummary struct {
	Cluster      string  `json:"cluster"`
	Nodes        int     `json:"nodes,omitempty"`
	Pods         int     `json:"pods,omitempty"`
	CPUUsedCores float64 `json:"cpuUsedCores,omitempty"`
	MemUsedBytes float64 `json:"memUsedBytes,omitempty"`
	// v0.9.9 — cluster toplam network hızı (node-exporter, lo hariç).
	// Best-effort: seri yoksa 0 kalır, UI kartı hiç render etmez.
	NetInBps  float64 `json:"netInBps,omitempty"`
	NetOutBps float64 `json:"netOutBps,omitempty"`
}

ClusterSummary — genel görünüm kartının verisi (v0.8.586, redesign audit §3.1). Her alan kendi sorgusundan BEST-EFFORT dolar: token tenancy-port'a bağlıysa node ailesi boş kalır ama pod sayısı yine gelir (kısmi kart > hata kartı). Dört sorgunun DÖRDÜ de başarısızsa cluster erişilemez sayılır ve hata döner.

type NamespaceRow added in v0.8.588

type NamespaceRow struct {
	Cluster   string  `json:"cluster"`
	Namespace string  `json:"namespace"`
	Pods      int     `json:"pods,omitempty"`
	CPUCores  float64 `json:"cpuCores"`
	MemBytes  float64 `json:"memBytes"`
}

NamespaceRow — bir namespace'in rollup satırı (v0.8.588, redesign audit §3.3). Ayrı sorgudan gelir — pod listesinin topk kesmesinden ETKİLENMEZ (toplamlar tam).

type NetTrendPoint added in v0.9.9

type NetTrendPoint struct {
	Bucket int64   `json:"bucket"`
	InBps  float64 `json:"inBps"`
	OutBps float64 `json:"outBps"`
}

NetTrendPoint — cluster network throughput trendi (v0.9.9): dakika bucket'ında in/out byte/s.

type NodeRow added in v0.8.582

type NodeRow struct {
	Cluster  string  `json:"cluster"`
	Node     string  `json:"node"`
	CPUCores float64 `json:"cpuCores"`
	MemBytes float64 `json:"memBytes"`
	CPUPct   float64 `json:"cpuPct,omitempty"`
	MemPct   float64 `json:"memPct,omitempty"`
	// v0.9.9 — node network hızı (node-exporter, lo hariç; best-effort).
	NetInBps  float64 `json:"netInBps,omitempty"`
	NetOutBps float64 `json:"netOutBps,omitempty"`
}

NodeRow — bir node'un anlık CPU/memory kullanımı (v0.8.582, audit: clusters-node-metrics-audit.md §3). Node = kube_node_info eşleşirse gerçek node adı, yoksa instance (ip:port). Pct'ler kendi paydalarına oran: CPUPct çekirdek sayısına (best-effort — 0 = bilinmiyor), MemPct MemTotal'a (zorunlu aileden, hep dolu).

type PodRow

type PodRow struct {
	Cluster   string  `json:"cluster"`
	Namespace string  `json:"namespace"`
	Pod       string  `json:"pod"`
	CPUCores  float64 `json:"cpuCores"`
	MemBytes  float64 `json:"memBytes"`
	CPUPct    float64 `json:"cpuPct,omitempty"`
	MemPct    float64 `json:"memPct,omitempty"`
	// Request-based percentages (v0.8.580) — provisioning accuracy
	// axis, alongside the limit-based throttle/OOM axis above. Can
	// legitimately exceed 100 (pod using more than it requested) —
	// deliberately NOT clamped like the limit pcts; the overshoot
	// IS the signal. 0 = requests not exposed (best-effort).
	CPUPctOfReq float64 `json:"cpuPctOfReq,omitempty"`
	MemPctOfReq float64 `json:"memPctOfReq,omitempty"`
	// Ham limit/request değerleri (v0.9.3, trend-upgrade audit §1
	// düzeltmesi): threshold referans ÇİZGİLERİ mutlak değer ister
	// (cores/bytes ekseninde) — yüzdeler yetmez. acc'ta zaten
	// vardı, satıra indirildi; 0 = bilinmiyor.
	CPULimitCores   float64 `json:"cpuLimitCores,omitempty"`
	MemLimitBytes   float64 `json:"memLimitBytes,omitempty"`
	CPURequestCores float64 `json:"cpuRequestCores,omitempty"`
	MemRequestBytes float64 `json:"memRequestBytes,omitempty"`
	// v0.9.9 — pod network hızı (cAdvisor, best-effort).
	NetInBps  float64 `json:"netInBps,omitempty"`
	NetOutBps float64 `json:"netOutBps,omitempty"`
}

PodRow is one (cluster, namespace, pod) sample from the merged instant queries. CPU is CORES (rate of cpu-seconds), not the 0-1 utilization ratio HostRow carries — deliberately a separate shape (audit §7). Pct fields are 0 when the cluster doesn't expose kube-state-metrics limits — same "0 = unknown" contract HostRow.MemPct already established.

type PodSeriesTrend added in v0.9.3

type PodSeriesTrend struct {
	Pod   string       `json:"pod"`
	Trend []TrendPoint `json:"trend"`
}

PodSeriesTrend — multi-pod görünümün seri birimi (v0.9.3): bir pod'un dakika-bucket trendi.

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service holds the live cluster list. Concurrency contract is tempo's: RWMutex around the config, background refresh poll keeping multi-pod deployments in sync via the shared blob.

func New

func New() *Service

func (*Service) ClusterByName

func (s *Service) ClusterByName(name string) (ClusterConfig, bool)

ClusterByName returns the ENABLED cluster entry for name.

func (*Service) Configure

func (s *Service) Configure(cfg Settings)

Configure swaps the live cluster list.

func (*Service) CurrentSettings

func (s *Service) CurrentSettings() Settings

CurrentSettings — full config INCLUDING tokens; only for the PUT handler's stored-token merge. Never echo over the wire (tempo contract).

func (*Service) HasEnabledClusters

func (s *Service) HasEnabledClusters() bool

HasEnabledClusters gates the /clusters surface: false → the page shows its Empty state without any HTTP attempts.

func (*Service) LoadPersisted

func (s *Service) LoadPersisted(ctx context.Context, store settingsStore) error

LoadPersisted hydrates from system_settings. Missing blob = empty list (HasEnabledClusters reports false; handlers 404).

func (*Service) NamespaceMetrics added in v0.8.588

func (s *Service) NamespaceMetrics(ctx context.Context, c ClusterConfig) ([]NamespaceRow, error)

NamespaceMetrics — cpu+mem zorunlu (2 sorgu), pod sayısı best-effort (1 sorgu; aynı metrik ailesi, pratikte hep döner).

func (*Service) NamespacePodsTrend added in v0.9.3

func (s *Service) NamespacePodsTrend(ctx context.Context, c ClusterConfig, namespace string, from, to time.Time) ([]PodSeriesTrend, int, error)

NamespacePodsTrend — namespace'in pod başına dakika-bucket trendleri (v0.9.3). Sorgu topk'siz (adım-başına set kayması kırar — promql.go notu); top-10 seçimi ortalama CPU'ya göre Go'da, cpu+mem AYNI pod setine filtrelenir. İkinci dönüş: kesme öncesi toplam pod sayısı ("top 10 of N" etiketi için).

func (*Service) NamespaceTrend added in v0.9.2

func (s *Service) NamespaceTrend(ctx context.Context, c ClusterConfig, namespace string, from, to time.Time) ([]TrendPoint, error)

NamespaceTrend — PodTrend'in namespace-scoped aynası (v0.9.2): aynı dakika-bucket sözleşmesi, pod pini yok — namespace toplamı.

func (*Service) NetworkTrend added in v0.9.9

func (s *Service) NetworkTrend(ctx context.Context, c ClusterConfig, from, to time.Time) ([]NetTrendPoint, error)

NetworkTrend — cluster toplam ağ hızının dakika-bucket trendi (Overview throughput grafiği). rangeTrend'in net karşılığı; iki sorgu da zorunlu (grafiğin kendisi bu — best-effort'luk üst katmanda: seri boşsa UI grafiği hiç göstermez).

func (*Service) NodeMetrics added in v0.8.582

func (s *Service) NodeMetrics(ctx context.Context, c ClusterConfig) ([]NodeRow, error)

NodeMetrics — PodMetrics'in node-scope aynası: 3 zorunlu sorgu (cpu used, mem total, mem avail) + 2 best-effort (çekirdek sayısı, kube_node_info ad güzelleştirmesi). Sabit 5 sorgu/cluster.

func (*Service) PodMetrics

func (s *Service) PodMetrics(ctx context.Context, c ClusterConfig) ([]PodRow, error)

PodMetrics runs the per-cluster instant queries (CPU rate, working-set memory, cpu/mem limits) and merges them by (namespace, pod). Exactly four queries per cluster regardless of pod count — never a query per pod (audit §4).

func (*Service) PodTrend

func (s *Service) PodTrend(ctx context.Context, c ClusterConfig, namespace, pod string, from, to time.Time) ([]TrendPoint, error)

PodTrend returns per-minute CPU + memory for ONE pod (drawer path — bounded by construction). step=60 mirrors the HostTrendPoint minute-bucket contract.

func (*Service) SavePersisted

func (s *Service) SavePersisted(ctx context.Context, store settingsStore, cfg Settings) error

SavePersisted writes the merged config (handler does the empty-token-preserves-stored merge first) and swaps it live.

func (*Service) Snapshot

func (s *Service) Snapshot() Snapshot

Snapshot returns the masked config for the settings UI.

func (*Service) StartConfigRefresh

func (s *Service) StartConfigRefresh(ctx context.Context, store settingsStore, interval time.Duration)

StartConfigRefresh — multi-pod blob sync, 30s default (tempo v0.5.324 precedent). Run as a goroutine from main().

func (*Service) Summary added in v0.8.586

func (s *Service) Summary(ctx context.Context, c ClusterConfig) (ClusterSummary, error)

Summary — kart başına sabit 4 skaler sorgu (topk'li vektör yok; pod sayısı topk kesmesiz TAM).

type Settings

type Settings struct {
	Clusters []ClusterConfig `json:"clusters"`
}

Settings is the persisted blob: the whole cluster list, written atomically (custom_roles convention — no per-row races at the realistic N≤20 scale).

type Snapshot

type Snapshot struct {
	Clusters []ClusterSnapshot `json:"clusters"`
}

Snapshot is what GET /api/settings/thanos returns.

type TrendPoint

type TrendPoint struct {
	Bucket   int64   `json:"bucket"`
	CPUCores float64 `json:"cpuCores"`
	MemBytes float64 `json:"memBytes"`
}

TrendPoint matches HostTrendPoint's bucket contract: unix SECONDS on minute boundaries, so the frontend drawer reuses the same rendering path.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL