Clusters métriques clusterpath

MetricClusterer fournit une dimension d'URL scopée par tenant avec une borne haute, adaptée à l'agrégation de compteurs de hits. Il est distinct de Clusterer : la normalisation d'URL peut apprendre des templates précis tandis que les métriques émettent un nombre fixe, sûr pour les dashboards, d'IDs de cluster.

Voir clusterpath pour le normaliseur sous-jacent.

Budget par défaut (96 IDs par tenant/site)

IDsRôle
8Fallbacks fixes : api, image, script, style, font, page, media, other
58Templates de routes canoniques à plus fort impact
30Familles déterministes hôte, premier segment de chemin et classe de ressource

La sélection des routes et familles pondère la part de hits. Les IDs actifs reçoivent un avantage de promotion : une nouvelle route doit être significativement plus importante avant de déplacer un cluster existant. Les chaînes de requête ne sont jamais incluses dans les labels métriques.

Cycle de vie

  1. Entraîner le normaliseur sur un historique représentatif.
  2. FreezeNormalizer pour rendre le modèle de templates immuable.
  3. Observe les URL pour accumuler les compteurs de sélection.
  4. Rebalance à la frontière d'une fenêtre de reporting pour sélectionner le dictionnaire.
  5. Persister le dictionnaire avec son horodatage effectif.
  6. ResetWindow avant la fenêtre suivante.

Avec un modèle de templates immuable, Rebalance est la seule opération qui change les assignations. Les IDs peuvent être réutilisés après un rebalance futur : les requêtes dashboard historiques doivent résoudre un ID avec le dictionnaire actif à l'horodatage des données.

Utilisation bibliothèque

Entraînez sur l'historique avant de servir des événements live pour que le dictionnaire initial soit utile plutôt que dominé par les fallbacks :

m := clusterpath.NewMetricClusterer(clusterpath.MetricConfig{MaxClusters: 96})

for _, event := range historicalEvents {
    m.Train([]byte(event.URL))
}
m.FreezeNormalizer()
for _, event := range historicalEvents {
    m.Observe([]byte(event.URL))
}
m.Rebalance()
dictionaryStore.Save(tenantID, time.Now(), m.Clusters())
m.ResetWindow()

Pour chaque événement live, écrivez des compteurs additifs clés par tenant, bucket temporel et ID renvoyé :

cluster := m.Observe([]byte(event.URL))
metricStore.Add(event.Timestamp, tenantID, cluster.ID, 1)

Flushez la fenêtre courante avant de changer son dictionnaire :

metricStore.Flush()
m.Rebalance()
dictionaryStore.Save(tenantID, time.Now(), m.Clusters())
m.ResetWindow()
  • Utilisez Assign pour rejouer des URL contre le dictionnaire courant sans modifier les compteurs de sélection.
  • Un MetricClusterer appartient à une goroutine. Exécutez-en un par tenant ou sérialisez l'accès à un dictionnaire partagé.

CLI : rapport hors ligne

go run ./cmd/metriccluster \
  -in testdata/url-clusters.txt \
  -out metric_clusters.tsv

La commande lit son entrée trois fois : entraîner la normalisation, sélectionner un dictionnaire métrique avec le modèle figé, puis assigner chaque URL et écrire les comptes agrégés. L'entrée doit être un fichier régulier seekable.

CLI : rapport fenêtré en ligne

Pour un flux single-pass, passez -window-size. La commande apprend les templates en ligne et rebalance le dictionnaire à 96 IDs après chaque fenêtre. Le rapport garde chaque version de dictionnaire séparée — le même ID de cluster peut représenter une route différente après un rebalance ultérieur :

cat requests.tsv | go run ./cmd/metriccluster \
  -in - \
  -window-size 100000 \
  -out windowed_metric_clusters.tsv

La sortie a une ligne pour chaque ID actif de chaque version de dictionnaire, avec les totaux de hits. La fenêtre initiale n'utilise que les IDs de fallback pendant que les candidats sont collectés ; les fenêtres suivantes utilisent le dictionnaire sélectionné à partir de la fenêtre précédente.

Ce mode convient lorsque chaque version est stockée avec sa fenêtre de reporting. Utilisez un dictionnaire figé persisté pour des IDs stables sur toutes les fenêtres.

Checklist opérationnelle

  • Entraînez sur un trafic représentatif avant le premier rebalance live.
  • Associez toujours les IDs métriques à la version de dictionnaire (et la plage temporelle) qui les a produits.
  • Flushez les stores avant Rebalance + ResetWindow.
  • Ne partagez pas un MetricClusterer entre goroutines sans verrou externe.
  • Gardez les chaînes de requête hors des labels — c'est intentionnel pour la sécurité de cardinalité.

Suite