topology

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Sep 5, 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"`
}

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