Documentation
¶
Overview ¶
Package cohort partitions a fleet into groups of clusters that look like each other. User-supplied tags win when present. Without tags, agglomerative clustering on a feature vector groups similar clusters so that drift detection can run within cohort instead of across the entire fleet.
Index ¶
Constants ¶
const DefaultTagKey = "cohort"
DefaultTagKey is the cluster-tag key that carries a cohort label.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ClusterProfile ¶
type ClusterProfile struct {
// Name is the cluster name.
Name string
// Features is the normalized feature vector. All profiles share the
// same feature order.
Features []float64
// Tag is the user-supplied cohort label, "" when unset.
Tag string
}
ClusterProfile is the per-cluster input to Assign. Features must be aligned across profiles, in the same order, and already normalized to roughly [0,1]. Tag is the user-supplied cohort label or "" if none was set.
func Profiles ¶
func Profiles(clusters []string, sections SectionLookup, tags map[string]string) []ClusterProfile
Profiles builds normalized feature vectors for every cluster in the fleet. Each feature is min-max normalized across the fleet to [0,1] so dimensions with large absolute ranges do not dominate distance calculations. Missing values are imputed with the per-feature fleet median before normalization. tags maps cluster name to its user-supplied cohort label (empty string when none).
type Cohort ¶
type Cohort struct {
// Name is the cohort label. For tagged cohorts this is the tag value.
// For auto-detected cohorts this is "auto-N" with a stable index.
Name string `json:"name"`
// Source identifies how this cohort was produced.
Source Source `json:"source"`
// Clusters lists the member cluster names, sorted for stable output.
Clusters []string `json:"clusters"`
}
Cohort is a group of clusters that look similar enough to share a baseline.
func Assign ¶
func Assign(profiles []ClusterProfile, opts Options) []Cohort
Assign partitions clusters into cohorts. Profiles carrying a non-empty Tag land in tagged cohorts named after the tag. Untagged profiles get auto-assigned via average-linkage agglomerative clustering on their feature vectors, with K chosen from the largest gap in the merge sequence. When the fleet is too small to subdivide, every cluster lands in a single "fleet" cohort.
type Options ¶
type Options struct {
// MinClusters is the fleet size below which auto-cohorting is skipped.
// Zero means use the package default.
MinClusters int
// MinCohortSize is the smallest cohort the algorithm will keep.
// Cohorts below this size are folded into their nearest neighbor.
// Zero means use the package default.
MinCohortSize int
// MaxCohorts caps the number of auto-detected cohorts.
// Zero means use the package default.
MaxCohorts int
}
Options controls cohort assignment.
type SectionLookup ¶
type SectionLookup interface {
// PerCluster returns the raw per-cluster data for a scanner. The map key
// is the cluster name. Returns nil when the scanner is absent.
PerCluster(scanner string) map[string]any
}
SectionLookup is the minimal interface Profiles needs to walk a Report without depending on the report package. Callers wrap their Report.Sections in something that satisfies this.
type Source ¶
type Source string
Source indicates how a cohort was determined.
const ( // SourceTagged means the cohort came from a user-supplied cluster tag. SourceTagged Source = "tagged" // SourceAuto means the cohort was derived by clustering scanner data. SourceAuto Source = "auto" // SourceFleet means the fleet was too small or too uniform to subdivide. SourceFleet Source = "fleet" )