Skip to content

Commit 3e83af5

Browse files
committed
Fixing how ring ownership is calculated on the ring status page
Signed-off-by: alanprot <alanprot@gmail.com>
1 parent a7ee7bd commit 3e83af5

File tree

2 files changed

+51
-13
lines changed

2 files changed

+51
-13
lines changed

pkg/ring/http.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ const pageContent = `
3838
<th>Last Heartbeat</th>
3939
<th>Tokens</th>
4040
<th>Ownership</th>
41+
<th>Ownership Diff From Expected</th>
4142
<th>Actions</th>
4243
</tr>
4344
</thead>
@@ -56,6 +57,7 @@ const pageContent = `
5657
<td>{{ .HeartbeatTimestamp }}</td>
5758
<td>{{ .NumTokens }}</td>
5859
<td>{{ .Ownership }}%</td>
60+
<td>{{ .DiffOwnership }}%</td>
5961
<td><button name="forget" value="{{ .ID }}" type="submit">Forget</button></td>
6062
</tr>
6163
{{ end }}
@@ -114,6 +116,7 @@ type ingesterDesc struct {
114116
Tokens []uint32 `json:"tokens"`
115117
NumTokens int `json:"-"`
116118
Ownership float64 `json:"-"`
119+
DiffOwnership float64 `json:"-"`
117120
}
118121

119122
type httpResponse struct {
@@ -154,6 +157,7 @@ func (r *Ring) ServeHTTP(w http.ResponseWriter, req *http.Request) {
154157
storageLastUpdate := r.KVClient.LastUpdateTime(r.key)
155158
var ingesters []ingesterDesc
156159
_, owned := r.countTokens()
160+
numTokens, ownedByAz := r.countTokensByAz()
157161
for _, id := range ingesterIDs {
158162
ing := r.ringDesc.Ingesters[id]
159163
heartbeatTimestamp := time.Unix(ing.Timestamp, 0)
@@ -168,6 +172,19 @@ func (r *Ring) ServeHTTP(w http.ResponseWriter, req *http.Request) {
168172
registeredTimestamp = ing.GetRegisteredAt().String()
169173
}
170174

175+
var ownership float64
176+
var deltaOwnership float64
177+
178+
if r.cfg.ZoneAwarenessEnabled {
179+
ownership = (float64(ownedByAz[id]) / float64(math.MaxUint32)) * 100
180+
expectedOwnership := 1 / float64(len(numTokens[ing.Zone])) * 100
181+
deltaOwnership = (1 - expectedOwnership/ownership) * 100
182+
} else {
183+
ownership = (float64(owned[id]) / float64(math.MaxUint32)) * 100
184+
expectedOwnership := 1 / float64(len(owned)) * 100
185+
deltaOwnership = (1 - expectedOwnership/ownership) * 100
186+
}
187+
171188
ingesters = append(ingesters, ingesterDesc{
172189
ID: id,
173190
State: state,
@@ -177,7 +194,8 @@ func (r *Ring) ServeHTTP(w http.ResponseWriter, req *http.Request) {
177194
Tokens: ing.Tokens,
178195
Zone: ing.Zone,
179196
NumTokens: len(ing.Tokens),
180-
Ownership: (float64(owned[id]) / float64(math.MaxUint32)) * 100,
197+
Ownership: ownership,
198+
DiffOwnership: deltaOwnership,
181199
})
182200
}
183201

pkg/ring/ring.go

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -590,22 +590,42 @@ func (r *Ring) GetReplicationSetForOperation(op Operation) (ReplicationSet, erro
590590
}, nil
591591
}
592592

593+
func (r *Ring) countTokensByAz() (map[string]map[string]uint32, map[string]int64) {
594+
numTokens := map[string]map[string]uint32{}
595+
owned := map[string]int64{}
596+
597+
for zone, zonalTokens := range r.ringDesc.getTokensByZone() {
598+
numTokens[zone] = map[string]uint32{}
599+
for i := 1; i <= len(zonalTokens); i++ {
600+
index := i % len(zonalTokens)
601+
diff := tokenDistance(zonalTokens[i-1], zonalTokens[index])
602+
info := r.ringInstanceByToken[zonalTokens[index]]
603+
owned[info.InstanceID] = owned[info.InstanceID] + diff
604+
numTokens[zone][info.InstanceID] = numTokens[zone][info.InstanceID] + 1
605+
}
606+
}
607+
608+
// Set to 0 the number of owned tokens by instances which don't have tokens yet.
609+
for id, info := range r.ringDesc.Ingesters {
610+
if _, ok := owned[id]; !ok {
611+
owned[id] = 0
612+
numTokens[info.Zone][id] = 0
613+
}
614+
}
615+
616+
return numTokens, owned
617+
}
618+
593619
// countTokens returns the number of tokens and tokens within the range for each instance.
594620
// The ring read lock must be already taken when calling this function.
595-
func (r *Ring) countTokens() (map[string]uint32, map[string]uint32) {
596-
owned := map[string]uint32{}
621+
func (r *Ring) countTokens() (map[string]uint32, map[string]int64) {
622+
owned := map[string]int64{}
597623
numTokens := map[string]uint32{}
598-
for i, token := range r.ringTokens {
599-
var diff uint32
600-
601-
// Compute how many tokens are within the range.
602-
if i+1 == len(r.ringTokens) {
603-
diff = (math.MaxUint32 - token) + r.ringTokens[0]
604-
} else {
605-
diff = r.ringTokens[i+1] - token
606-
}
624+
for i := 1; i <= len(r.ringTokens); i++ { // Compute how many tokens are within the range.
625+
index := i % len(r.ringTokens)
626+
diff := tokenDistance(r.ringTokens[i-1], r.ringTokens[index])
607627

608-
info := r.ringInstanceByToken[token]
628+
info := r.ringInstanceByToken[r.ringTokens[index]]
609629
numTokens[info.InstanceID] = numTokens[info.InstanceID] + 1
610630
owned[info.InstanceID] = owned[info.InstanceID] + diff
611631
}

0 commit comments

Comments
 (0)