mirror of
https://github.com/grafana/loki.git
synced 2026-03-13 09:33:58 +08:00
85 lines
2.3 KiB
Go
85 lines
2.3 KiB
Go
package analytics
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
jsoniter "github.com/json-iterator/go"
|
|
prom "github.com/prometheus/prometheus/web/api/v1"
|
|
|
|
"github.com/grafana/dskit/kv/memberlist"
|
|
)
|
|
|
|
// ClusterSeed is the seed for the usage stats.
|
|
// A unique ID is generated for each cluster.
|
|
type ClusterSeed struct {
|
|
UID string `json:"UID"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
prom.PrometheusVersion `json:"version"`
|
|
}
|
|
|
|
// Merge implements the memberlist.Mergeable interface.
|
|
// It allow to merge the content of two different seeds.
|
|
func (c *ClusterSeed) Merge(mergeable memberlist.Mergeable, _ bool) (change memberlist.Mergeable, err error) {
|
|
if mergeable == nil {
|
|
return nil, nil
|
|
}
|
|
other, ok := mergeable.(*ClusterSeed)
|
|
if !ok {
|
|
return nil, fmt.Errorf("expected *usagestats.ClusterSeed, got %T", mergeable)
|
|
}
|
|
if other == nil {
|
|
return nil, nil
|
|
}
|
|
// if we already have (c) the oldest key, then should not request change.
|
|
if c.CreatedAt.Before(other.CreatedAt) {
|
|
return nil, nil
|
|
}
|
|
if c.CreatedAt.Equal(other.CreatedAt) {
|
|
// if we have the exact same creation date but the key is different
|
|
// we take the smallest UID using string alphabetical comparison to ensure stability.
|
|
if c.UID > other.UID {
|
|
*c = *other
|
|
return other, nil
|
|
}
|
|
return nil, nil
|
|
}
|
|
// if our seed is not the oldest, then we should request a change.
|
|
*c = *other
|
|
return other, nil
|
|
}
|
|
|
|
// MergeContent tells if the content of the two seeds are the same.
|
|
func (c *ClusterSeed) MergeContent() []string {
|
|
return []string{c.UID}
|
|
}
|
|
|
|
// RemoveTombstones is not required for usagestats
|
|
func (c *ClusterSeed) RemoveTombstones(_ time.Time) (total, removed int) {
|
|
return 0, 0
|
|
}
|
|
|
|
func (c *ClusterSeed) Clone() memberlist.Mergeable {
|
|
clone := *c
|
|
return &clone
|
|
}
|
|
|
|
var JSONCodec = jsonCodec{}
|
|
|
|
type jsonCodec struct{}
|
|
|
|
// todo we need to use the default codec for the rest of the code
|
|
// currently crashing because the in-memory kvstore use a singleton.
|
|
func (jsonCodec) Decode(data []byte) (interface{}, error) {
|
|
var seed ClusterSeed
|
|
if err := jsoniter.ConfigFastest.Unmarshal(data, &seed); err != nil {
|
|
return nil, err
|
|
}
|
|
return &seed, nil
|
|
}
|
|
|
|
func (jsonCodec) Encode(obj interface{}) ([]byte, error) {
|
|
return jsoniter.ConfigFastest.Marshal(obj)
|
|
}
|
|
func (jsonCodec) CodecID() string { return "usagestats.jsonCodec" }
|