Help us shape the future of Go! Take the 2026 Go Developer Survey

topology

package
v0.6.3 Latest Latest
Warning

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

Go to latest
Published: Oct 20, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Overview

Package topology owns the mode-selected service-topology read contract.

Index

Constants

View Source
const (
	// MaxHostsPerNode caps the hosts list stamped on one service-map node.
	MaxHostsPerNode = 20
	// MaxServicesPerHost caps the services list carried by one host.
	MaxServicesPerHost = 100
)

Host projection bounds (#288). The registry already bounds hosts and service-host pairs per tenant; these bound what one response carries.

View Source
const (
	KindService = "service"
	KindHost    = "host"
)

Node kinds. A host entity (IsHostEntity) is rendered as a host by every consumer: it is never a service, never carries a CALLS edge and never enters a service count.

View Source
const (
	// RegistryMaxHostsPerTenant bounds distinct non-empty hosts per tenant.
	RegistryMaxHostsPerTenant = 1000
	// RegistryMaxEntriesPerTenant bounds service-host(-workload) entries per tenant.
	RegistryMaxEntriesPerTenant = 10000
	// RegistryIdleTTL evicts an entry no signal has touched for this long.
	RegistryIdleTTL = 24 * time.Hour
	// RegistryMaxValueBytes bounds service, host and workload values; the
	// persisted columns are 255 bytes wide on every adapter and an over-length
	// value would poison every later flush of the same batch.
	RegistryMaxValueBytes = 255
	// RegistryFlushInterval is the dirty-tick period used by Run.
	RegistryFlushInterval = 30 * time.Second
)

Resource registry bounds (#279). Constants, mirroring the SignalStore caps: a shared __other__ host would be exactly the cross-host merge the registry exists to avoid, so overflow is counted and dropped, never collapsed.

View Source
const (
	RegistryKindHost   = "host"
	RegistryKindPair   = "pair"
	RegistryKindLength = "length"
)

Overflow kinds, also the metric label values.

View Source
const HostPrefix = "host/"

HostPrefix is the reserved service-name namespace of host entities (#280): a resource carrying host.id or host.name and no service.name is identified as HostPrefix + host.name (host.id when there is no name). The registry schema is unchanged; the entity kind is derived from the name.

Variables

This section is empty.

Functions

func IsHostEntity

func IsHostEntity(service string) bool

IsHostEntity reports whether service names a host entity.

func NodeKind

func NodeKind(service string) string

NodeKind returns the kind of the named node.

Types

type AggregateProvider

type AggregateProvider struct {
	HostReader
	// contains filtered or unexported fields
}

AggregateProvider is both the ordinary mode-selected provider and the narrow aggregate projection source GraphRAG already consumes.

func NewAggregateProvider

func NewAggregateProvider(engine *aggregate.Engine) (*AggregateProvider, error)

func (*AggregateProvider) Identity

func (*AggregateProvider) PruneTopology

func (p *AggregateProvider) PruneTopology()

func (*AggregateProvider) Snapshot

func (p *AggregateProvider) Snapshot(ctx context.Context, q Query) (Snapshot, error)

func (*AggregateProvider) Source

func (*AggregateProvider) Source() Source

func (*AggregateProvider) TopologyEpoch

func (p *AggregateProvider) TopologyEpoch() uint64

The following methods implement graphrag.AggregateSource. Keeping that projection narrow avoids teaching GraphRAG about range queries.

func (*AggregateProvider) TopologyRevision

func (p *AggregateProvider) TopologyRevision(tenant string) uint64

func (*AggregateProvider) TopologySnapshot

func (p *AggregateProvider) TopologySnapshot(tenant string) aggregate.TopologySnapshot

func (*AggregateProvider) TopologyTenants

func (p *AggregateProvider) TopologyTenants() []string

type Edge

type Edge struct {
	Source       string  `json:"source"`
	Target       string  `json:"target"`
	CallCount    int64   `json:"call_count"`
	AvgLatencyMs float64 `json:"avg_latency_ms"`
	ErrorRate    float64 `json:"error_rate"`
	Status       string  `json:"status,omitempty"`
}

Edge is one directed service dependency.

type Host

type Host struct {
	Name         string    `json:"name"`
	ServiceCount int       `json:"service_count"`
	Services     []string  `json:"services"`
	LastSeen     time.Time `json:"last_seen"`
	Signals      []string  `json:"signals"`
}

Host is one host with the services observed on it. Services is sorted, never nil, capped at MaxServicesPerHost and never lists a host entity; ServiceCount is the uncapped total.

type HostProjection

type HostProjection struct {
	// Hosts is sorted by name and never nil.
	Hosts []Host
	// contains filtered or unexported fields
}

HostProjection is one tenant's host view derived from one registry snapshot: hosts with their services, and per service its hosts.

func ProjectHosts

func ProjectHosts(entries []ResourceEntry) HostProjection

ProjectHosts folds registry entries of one tenant into a HostProjection. Entries without a host contribute nothing.

func (HostProjection) Host

func (p HostProjection) Host(name string) (Host, bool)

Host returns the named host.

func (HostProjection) ServiceHosts

func (p HostProjection) ServiceHosts(service string) (int, []string)

ServiceHosts returns how many hosts service was observed on and the first MaxHostsPerNode of them, sorted.

type HostReader

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

HostReader is the single reader of the resource registry for every topology consumer. Both providers embed it, so legacy, shadow and aggregate answer host questions identically. Without a registry it projects nothing.

func (*HostReader) Hosts

func (h *HostReader) Hosts(ctx context.Context) HostProjection

Hosts projects the registry for the tenant on ctx. It is built per call: the registry snapshot is already sorted and bounded per tenant.

func (*HostReader) SetRegistry

func (h *HostReader) SetRegistry(r *Registry)

SetRegistry wires the registry read by Hosts.

type Identity

type Identity struct {
	Epoch    string `json:"epoch,omitempty"`
	Revision uint64 `json:"revision,omitempty"`
}

Identity orders full-replacement snapshots within one process generation.

func (Identity) String

func (i Identity) String() string

String returns the stable cache and stream identity.

type LegacyProvider

type LegacyProvider struct {
	HostReader
	// contains filtered or unexported fields
}

LegacyProvider preserves the existing historical repository query and the current GraphRAG/graph/DB preference for live topology.

func NewLegacyProvider

func NewLegacyProvider(repo legacyRepository, serviceGraph *graph.Graph, graphRAG *graphrag.GraphRAG) (*LegacyProvider, error)

func (*LegacyProvider) Identity

func (*LegacyProvider) Snapshot

func (p *LegacyProvider) Snapshot(ctx context.Context, q Query) (Snapshot, error)

func (*LegacyProvider) Source

func (*LegacyProvider) Source() Source

type Metadata

type Metadata struct {
	Source       Source    `json:"source,omitempty"`
	Start        time.Time `json:"start,omitempty"`
	End          time.Time `json:"end,omitempty"`
	Coverage     string    `json:"coverage,omitempty"`
	CoverageNote string    `json:"coverage_note,omitempty"`
	Epoch        string    `json:"epoch,omitempty"`
	Revision     uint64    `json:"revision,omitempty"`
	Truncated    bool      `json:"truncated,omitempty"`

	DroppedServices   uint64                     `json:"dropped_services,omitempty"`
	DroppedOperations uint64                     `json:"dropped_operations,omitempty"`
	DroppedEdges      uint64                     `json:"dropped_edges,omitempty"`
	DroppedMetrics    uint64                     `json:"dropped_metrics,omitempty"`
	IdentityCoverage  aggregate.IdentityCoverage `json:"identity_coverage"`
}

Metadata is additive ownership and completeness information.

func (Metadata) Identity

func (m Metadata) Identity() Identity

Identity returns the ordering pair carried by this metadata.

type Node

type Node struct {
	Name         string  `json:"name"`
	TotalTraces  int64   `json:"total_traces"`
	ErrorCount   int64   `json:"error_count"`
	AvgLatencyMs float64 `json:"avg_latency_ms"`

	RequestRateRPS    float64             `json:"request_rate_rps,omitempty"`
	ErrorRate         float64             `json:"error_rate,omitempty"`
	P99LatencyMs      float64             `json:"p99_latency_ms,omitempty"`
	LatencyProvenance *latency.Provenance `json:"latency_provenance,omitempty"`
	SpanCount         int64               `json:"span_count,omitempty"`
	HealthScore       float64             `json:"health_score,omitempty"`
	Status            string              `json:"status,omitempty"`
	Alerts            []string            `json:"alerts,omitempty"`

	// Host projection (#288), stamped by the provider from the resource
	// registry. Kind is KindService or KindHost; Hosts is sorted and capped
	// at MaxHostsPerNode while HostCount is the uncapped total.
	Kind      string   `json:"kind,omitempty"`
	HostCount int      `json:"host_count,omitempty"`
	Hosts     []string `json:"hosts,omitempty"`
}

Node is the wire-neutral service projection shared by all consumers.

type Provider

type Provider interface {
	Source() Source
	Identity(context.Context) Identity
	Snapshot(context.Context, Query) (Snapshot, error)
	// Hosts is the tenant-scoped host projection of the resource registry.
	// Every provider answers it from the same registry, so legacy, shadow
	// and aggregate agree on hosts.
	Hosts(context.Context) HostProjection
}

Provider is selected once from AGGREGATE_MODE and injected into every live topology consumer.

type Query

type Query struct {
	Start    time.Time
	End      time.Time
	Services []string
}

Query selects a range and an optional closed set of services. A zero range asks for the provider's current live replacement.

type Registry

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

Registry is the bounded in-memory resource registry. Registration is one mutex acquisition and one map lookup; the already-present path allocates nothing.

func NewRegistry

func NewRegistry(metrics *telemetry.Metrics) *Registry

NewRegistry returns an empty registry. metrics may be nil.

func (*Registry) Evict

func (r *Registry) Evict(now time.Time) int

Evict drops entries idle past RegistryIdleTTL at now and returns how many. Their rows are deleted by the next Flush.

func (*Registry) Flush

func (r *Registry) Flush(ctx context.Context, db *gorm.DB) error

Flush upserts dirty entries and deletes evicted rows. A failed write leaves the affected entries dirty (or evicted) for the next tick.

func (*Registry) Load

func (r *Registry) Load(ctx context.Context, db *gorm.DB) (int, error)

Load reloads persisted entries through the same bounds as Register. Rows already idle past the TTL are loaded too; the first tick evicts them and the following flush deletes their rows.

func (*Registry) Overflow

func (r *Registry) Overflow(tenant, kind string) uint64

Overflow returns how many registrations the bound of kind refused for tenant.

func (*Registry) Register

func (r *Registry) Register(tenant, service, host, workload, kind string, signal Signal, now time.Time) bool

Register records that signal arrived from the resource at now. It reports false when a per-tenant bound refused a new entry.

func (*Registry) Run

func (r *Registry) Run(ctx context.Context, db *gorm.DB, interval time.Duration)

Run evicts, publishes gauges and flushes on every tick until ctx is done. The caller flushes once more at shutdown.

func (*Registry) Snapshot

func (r *Registry) Snapshot() []ResourceEntry

Snapshot returns every live entry ordered by key.

func (*Registry) TenantSnapshot

func (r *Registry) TenantSnapshot(tenant string) []ResourceEntry

TenantSnapshot returns tenant's live entries ordered by key.

type ResourceEntry

type ResourceEntry struct {
	ResourceKey
	// Kind names the slot that filled Workload (pod|container|process), or "".
	Kind     string
	Signals  Signal
	LastSeen time.Time
}

ResourceEntry is one row of a read-only registry snapshot.

type ResourceKey

type ResourceKey struct {
	Tenant   string
	Service  string
	Host     string
	Workload string
}

ResourceKey identifies one registered resource. Host is host.id else host.name; Workload is k8s.pod.uid else container.id else process.pid. Both may be empty: a resource without a host registers the service alone.

type Signal

type Signal uint8

Signal is one bit of ResourceEntry.Signals.

const (
	SignalTraces Signal = 1 << iota
	SignalLogs
	SignalMetrics
)

func (Signal) Names

func (s Signal) Names() []string

Names renders the signal bits as sorted names.

type Snapshot

type Snapshot struct {
	Nodes []Node   `json:"nodes"`
	Edges []Edge   `json:"edges"`
	Meta  Metadata `json:"meta,omitempty"`
}

Snapshot is always a full replacement. Nodes and Edges are never nil.

type Source

type Source string

Source identifies the producer that owns a snapshot.

const (
	SourceLegacy    Source = "legacy"
	SourceAggregate Source = "aggregate"
)

Jump to

Keyboard shortcuts

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