-
Notifications
You must be signed in to change notification settings - Fork 38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat/Object count metrics #1712
Feat/Object count metrics #1712
Conversation
Codecov Report
@@ Coverage Diff @@
## master #1712 +/- ##
==========================================
+ Coverage 32.50% 32.60% +0.09%
==========================================
Files 337 338 +1
Lines 22701 22820 +119
==========================================
+ Hits 7380 7441 +61
- Misses 14708 14754 +46
- Partials 613 625 +12
📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
Agree, the total node's object count can be handled externally. Is it possible to add a separate per shard counter for logically available objects? For example, some objects may be inhumed, but not physically removed from the graveyard yet, so we could see the difference in the monitoring system. |
@realloc, that PR contains the metrics with physically stored objects (no split objects, tombstoned objects are included in the counter if they are not deleted by a shard yet). Do you mean to just add another counter that means the same but excludes objects that have TS/GC? |
Yes, there should be one counter with all types of objects available and one for all types of objects physically stored. |
// tracked since it was opened and initialized. | ||
// | ||
// Returns only the errors that do not allow reading counter | ||
// in bbolt database. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bolt?
return | ||
} | ||
|
||
// updateCounter updates the object counter. Must be called NOT for read-only |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// updateCounter updates the object counter. Must be called NOT for read-only | |
// updateCounter updates the object counter. Tx MUST be writable. |
// If inc == `true`, increases the counter, decreases otherwise. | ||
func (db *DB) updateCounter(tx *bbolt.Tx, delta uint64, inc bool) error { | ||
b := tx.Bucket(shardInfoBucket) | ||
if b != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
immediate return on nil
for smaller if
?
b := tx.Bucket(shardInfoBucket) | ||
if b != nil { | ||
var counter uint64 | ||
newCounter := make([]byte, 8) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alloc on miss only?
counter = binary.LittleEndian.Uint64(data) | ||
case 0: | ||
default: | ||
return nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it normal? Maybe panic?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well... ok, added panic
@fyrchik, ping
if inc { | ||
counter += delta | ||
} else { | ||
if counter <= delta { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Merge with else
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
merged but usually, i prefer not to use else if
} | ||
} | ||
|
||
err := db.updateCounter(tx, rawDeleted, false) | ||
if err != nil { | ||
return 0, fmt.Errorf("could not decrease object counter: %w", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe make it a pure feature and not fail the original op?
Same for PUT.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agree, removed return
, added error log
switch len(data) { | ||
case 8: | ||
counter = binary.LittleEndian.Uint64(data) | ||
case 0: | ||
default: | ||
panic(fmt.Errorf( | ||
"unexpected len of object counter value: %d", len(data)), | ||
) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think just checking len(data) == 8
would be enough.
db.log.Error("could not decrease object counter", | ||
zap.Error(err)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, let's not log anything inside of a transaction. It is potentially a blocking call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missed that it is inside a bolt TX
return back the returned code: no logging, direct err to a caller only
if err != nil { | ||
db.log.Error("could not increase object counter: %w", | ||
zap.Error(err)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here too. I think we can (should) return the error to the caller, updateCounter
has no logical errors.
pkg/metrics/object.go
Outdated
@@ -254,3 +270,15 @@ func (m objectServiceMetrics) AddPutPayload(ln int) { | |||
func (m objectServiceMetrics) AddGetPayload(ln int) { | |||
m.getPayload.Add(float64(ln)) | |||
} | |||
|
|||
func (m objectServiceMetrics) ChangeBy(shardID string, delta int) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change
what? Could you add ObjectCounter
to the name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed, only AddToObjectCounter(shardID string, delta int)
and SetObjectCounter(shardID string, v uint64)
are kept on the metrics side; wrappers still have Inc*
, Dec*
methods
pkg/metrics/object.go
Outdated
func (m objectServiceMetrics) IncObjectCounter(shardID string) { | ||
m.shardMetrics.With(prometheus.Labels{shardIDLabelKey: shardID}).Inc() | ||
} | ||
|
||
func (m objectServiceMetrics) DecObjectCounter(shardID string) { | ||
m.shardMetrics.With(prometheus.Labels{shardIDLabelKey: shardID}).Dec() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you decide to stay on 3 methods instead of a single AddToObjectCounter
which covers both inc
and dec
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
kept only two: Set*
and Add*
Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
Increment shard's object counter on successful `Put` calls and decrement on `Delete`. Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
Includes: 1. Renaming counter key to distinguish logical and physical objects 2. Version update dropping since changes could be done in a compatible way Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
Related to #1658
Does not contain the node's total object count since on the shard level it is quite easy to control objects but on the SE level it is not always clear whether a shard contains an object or not:
Delete
always calls shard'sInhume
notDelete
It is possible to solve (e.g. some SE'e atomic counter that could be passed to every shard) but IMO it is easier to calculate on a metric collector side.