-
Notifications
You must be signed in to change notification settings - Fork 140
CBG-4579: Add uint64 support to few metrics in sgw #7828
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
Changes from 5 commits
2e20636
455a2fb
1ef7ff7
f3d936e
4732fb1
4b5304d
85ae39e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -76,6 +76,7 @@ const ( | |||||||||
| StatUnitUnixTimestamp = "unix timestamp" | ||||||||||
|
|
||||||||||
| StatFormatInt = "int" | ||||||||||
| StatFormatUint = "uint" | ||||||||||
| StatFormatFloat = "float" | ||||||||||
| StatFormatDuration = "duration" | ||||||||||
| StatFormatBool = "bool" | ||||||||||
|
|
@@ -472,10 +473,10 @@ type CacheStats struct { | |||||||||
| // The highest sequence number cached. | ||||||||||
| // | ||||||||||
| // There may be skipped sequences lower than high_seq_cached. | ||||||||||
| HighSeqCached *SgwIntStat `json:"high_seq_cached"` | ||||||||||
| HighSeqCached *SgwUint64Stat `json:"high_seq_cached"` | ||||||||||
| // The highest contiguous sequence number that has been cached. | ||||||||||
| HighSeqStable *SgwIntStat `json:"high_seq_stable"` | ||||||||||
| NonMobileIgnoredCount *SgwIntStat `json:"non_mobile_ignored_count"` | ||||||||||
| HighSeqStable *SgwUint64Stat `json:"high_seq_stable"` | ||||||||||
| NonMobileIgnoredCount *SgwIntStat `json:"non_mobile_ignored_count"` | ||||||||||
| // The total number of active channels. | ||||||||||
| NumActiveChannels *SgwIntStat `json:"num_active_channels"` | ||||||||||
| // The total number of skipped sequences. This is a cumulative value. | ||||||||||
|
|
@@ -606,9 +607,9 @@ type DatabaseStats struct { | |||||||||
| ReplicationBytesReceived *SgwIntStat `json:"replication_bytes_received"` | ||||||||||
| ReplicationBytesSent *SgwIntStat `json:"replication_bytes_sent"` | ||||||||||
| // The compaction_attachment_start_time. | ||||||||||
| CompactionAttachmentStartTime *SgwIntStat `json:"compaction_attachment_start_time"` | ||||||||||
| CompactionAttachmentStartTime *SgwUint64Stat `json:"compaction_attachment_start_time"` | ||||||||||
| // The compaction_tombstone_start_time. | ||||||||||
| CompactionTombstoneStartTime *SgwIntStat `json:"compaction_tombstone_start_time"` | ||||||||||
| CompactionTombstoneStartTime *SgwUint64Stat `json:"compaction_tombstone_start_time"` | ||||||||||
| // The total number of writes that left the document in a conflicted state. Includes new conflicts, and mutations that don’t resolve existing conflicts. | ||||||||||
| ConflictWriteCount *SgwIntStat `json:"conflict_write_count"` | ||||||||||
| // The total number of instances during import when the document cas had changed, but the document was not imported because the document body had not changed. | ||||||||||
|
|
@@ -630,7 +631,7 @@ type DatabaseStats struct { | |||||||||
| // The total size of xattrs written (in bytes). | ||||||||||
| DocWritesXattrBytes *SgwIntStat `json:"doc_writes_xattr_bytes"` | ||||||||||
| // Highest sequence number seen on the caching DCP feed. | ||||||||||
| HighSeqFeed *SgwIntStat `json:"high_seq_feed"` | ||||||||||
| HighSeqFeed *SgwUint64Stat `json:"high_seq_feed"` | ||||||||||
| // The number of attachments compacted | ||||||||||
| NumAttachmentsCompacted *SgwIntStat `json:"num_attachments_compacted"` | ||||||||||
| // The total number of documents read via Couchbase Lite 2.x replication since Sync Gateway node startup. | ||||||||||
|
|
@@ -653,19 +654,19 @@ type DatabaseStats struct { | |||||||||
| // The total amount of bytes read over the public REST api | ||||||||||
| PublicRestBytesRead *SgwIntStat `json:"public_rest_bytes_read"` | ||||||||||
| // The value of the last sequence number assigned. Callers using Set should be holding a mutex or ensure concurrent updates to this value are otherwise safe. | ||||||||||
| LastSequenceAssignedValue *SgwIntStat `json:"last_sequence_assigned_value"` // TODO: CBG-4579 - Replace with SgwUintStat stat | ||||||||||
| LastSequenceAssignedValue *SgwUint64Stat `json:"last_sequence_assigned_value"` | ||||||||||
| // The total number of sequence numbers assigned. | ||||||||||
| SequenceAssignedCount *SgwIntStat `json:"sequence_assigned_count"` | ||||||||||
| SequenceAssignedCount *SgwUint64Stat `json:"sequence_assigned_count"` | ||||||||||
| // The total number of high sequence lookups. | ||||||||||
| SequenceGetCount *SgwIntStat `json:"sequence_get_count"` | ||||||||||
| // The total number of times the sequence counter document has been incremented. | ||||||||||
| SequenceIncrCount *SgwIntStat `json:"sequence_incr_count"` | ||||||||||
| // The total number of unused, reserved sequences released by Sync Gateway. | ||||||||||
| SequenceReleasedCount *SgwIntStat `json:"sequence_released_count"` | ||||||||||
| SequenceReleasedCount *SgwUint64Stat `json:"sequence_released_count"` | ||||||||||
| // The value of the last sequence number reserved (which may not yet be assigned). Callers using Set should be holding a mutex or ensure concurrent updates to this value are otherwise safe. | ||||||||||
| LastSequenceReservedValue *SgwIntStat `json:"last_sequence_reserved_value"` // TODO: CBG-4579 - Replace with SgwUintStat stat | ||||||||||
| LastSequenceReservedValue *SgwUint64Stat `json:"last_sequence_reserved_value"` | ||||||||||
| // The total number of sequences reserved by Sync Gateway. | ||||||||||
| SequenceReservedCount *SgwIntStat `json:"sequence_reserved_count"` | ||||||||||
| SequenceReservedCount *SgwUint64Stat `json:"sequence_reserved_count"` | ||||||||||
| // The total number of corrupt sequences above the MaxSequencesToRelease threshold seen at the sequence allocator | ||||||||||
| CorruptSequenceCount *SgwIntStat `json:"corrupt_sequence_count"` | ||||||||||
| // The total number of warnings relating to the channel name size. | ||||||||||
|
|
@@ -986,6 +987,11 @@ type SgwIntStat struct { | |||||||||
| AtomicInt | ||||||||||
| } | ||||||||||
|
|
||||||||||
| type SgwUint64Stat struct { | ||||||||||
| SgwStat | ||||||||||
| atomic.Uint64 | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // uint64 is used here because atomic ints do not support floats. Floats are encoded to uint64 | ||||||||||
| type SgwFloatStat struct { | ||||||||||
| SgwStat | ||||||||||
|
|
@@ -1079,6 +1085,102 @@ func (s *SgwIntStat) String() string { | |||||||||
| return strconv.FormatInt(s.Value(), 10) | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // NewUIntStat creates and returns a new unsigned integer Sync Gateway stat (SgwUint64Stat). | ||||||||||
| // The stat is initialized to initialValue and, unless SkipPrometheusStatsRegistration is true, | ||||||||||
| // is registered with Prometheus. It returns an error if required metadata is missing or if | ||||||||||
| // Prometheus registration fails. | ||||||||||
| // | ||||||||||
| // Parameters: | ||||||||||
| // | ||||||||||
| // subsystem: The Prometheus subsystem segment (e.g. resource_utilization, database) used to build the fully qualified metric name. | ||||||||||
| // key: The short metric key appended to the subsystem to form the final metric name. | ||||||||||
| // unit: The unit of measurement (e.g. bytes, seconds). Used for metadata export tooling. | ||||||||||
| // description: Human-readable help text for the metric. Must be non-empty. | ||||||||||
| // addedVersion: The Sync Gateway version the stat was introduced. Must be non-empty. | ||||||||||
| // deprecatedVersion: The version the stat was deprecated, or empty if not deprecated. | ||||||||||
| // stability: The stability level (committed, volatile, or internal). Must be non-empty. | ||||||||||
| // labelKeys: Slice of label keys for constant labels. Must align index-wise with labelVals. | ||||||||||
| // labelVals: Slice of label values corresponding to labelKeys. Length must match labelKeys. | ||||||||||
| // statValueType: The Prometheus value type (counter or gauge) controlling exposition semantics. | ||||||||||
| // initialValue: The initial uint64 value assigned to the stat's atomic counter. | ||||||||||
| // | ||||||||||
| // Behavior: | ||||||||||
| // - Validates required metadata (description, addedVersion, stability). | ||||||||||
| // - Builds a Prometheus descriptor with any constant labels. | ||||||||||
| // - Sets the initial value atomically. | ||||||||||
| // - Registers the metric with Prometheus unless SkipPrometheusStatsRegistration is true. | ||||||||||
| // - Returns (*SgwUint64Stat, error) where error is non-nil on validation or registration failure. | ||||||||||
| // | ||||||||||
| // Concurrency: | ||||||||||
| // | ||||||||||
| // The underlying value uses atomic.Uint64 for safe concurrent mutation by callers. | ||||||||||
| // | ||||||||||
| // Errors: | ||||||||||
| // | ||||||||||
| // Returned if required fields are missing or if prometheus.Register fails (e.g. duplicate registration). | ||||||||||
| func NewUIntStat(subsystem, key, unit, description, addedVersion, deprecatedVersion, stability string, labelKeys, labelVals []string, statValueType prometheus.ValueType, initialValue uint64) (*SgwUint64Stat, error) { | ||||||||||
| stat, err := newSGWStat(subsystem, key, unit, description, addedVersion, deprecatedVersion, stability, labelKeys, labelVals, statValueType) | ||||||||||
| if err != nil { | ||||||||||
| return nil, err | ||||||||||
| } | ||||||||||
|
|
||||||||||
| wrappedStat := &SgwUint64Stat{ | ||||||||||
| SgwStat: *stat, | ||||||||||
| } | ||||||||||
|
|
||||||||||
| wrappedStat.Set(initialValue) | ||||||||||
|
|
||||||||||
| if !SkipPrometheusStatsRegistration { | ||||||||||
| err := prometheus.Register(wrappedStat) | ||||||||||
| if err != nil { | ||||||||||
| return nil, err | ||||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
| return wrappedStat, nil | ||||||||||
| } | ||||||||||
|
|
||||||||||
| func (s *SgwUint64Stat) FormatString() string { | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
This shows up in documentation https://docs.couchbase.com/sync-gateway/current/manage/stats-monitoring-prometheus.html and https://docs.couchbase.com/sync-gateway/current/manage/stats-monitoring-json.html but curiously neither page use this value and it isn't generated by the generator that is used to update these pages.
|
||||||||||
| return StatFormatUint | ||||||||||
| } | ||||||||||
|
|
||||||||||
| func (s *SgwUint64Stat) Describe(ch chan<- *prometheus.Desc) { | ||||||||||
RIT3shSapata marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
| ch <- s.statDesc | ||||||||||
| } | ||||||||||
|
|
||||||||||
| func (s *SgwUint64Stat) Collect(ch chan<- prometheus.Metric) { | ||||||||||
RIT3shSapata marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
| ch <- prometheus.MustNewConstMetric(s.statDesc, s.statValueType, float64(s.Value())) | ||||||||||
| } | ||||||||||
|
|
||||||||||
| func (s *SgwUint64Stat) MarshalJSON() ([]byte, error) { | ||||||||||
| return []byte(strconv.FormatUint(s.Value(), 10)), nil | ||||||||||
| } | ||||||||||
|
|
||||||||||
| func (s *SgwUint64Stat) String() string { | ||||||||||
| return strconv.FormatUint(s.Value(), 10) | ||||||||||
| } | ||||||||||
|
|
||||||||||
| func (s *SgwUint64Stat) Set(value uint64) { | ||||||||||
RIT3shSapata marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
| s.Store(value) | ||||||||||
| } | ||||||||||
|
|
||||||||||
| func (s *SgwUint64Stat) SetIfMax(value uint64) { | ||||||||||
| for { | ||||||||||
| cur := s.Load() | ||||||||||
| if cur >= value { | ||||||||||
| return | ||||||||||
| } | ||||||||||
|
|
||||||||||
| if s.CompareAndSwap(cur, value) { | ||||||||||
| return | ||||||||||
| } | ||||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
| func (s *SgwUint64Stat) Value() uint64 { | ||||||||||
RIT3shSapata marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
| return s.Load() | ||||||||||
| } | ||||||||||
|
|
||||||||||
| func NewFloatStat(subsystem, key, unit, description, addedVersion, deprecatedVersion, stability string, labelKeys, labelVals []string, statValueType prometheus.ValueType, initialValue float64) (*SgwFloatStat, error) { | ||||||||||
| stat, err := newSGWStat(subsystem, key, unit, description, addedVersion, deprecatedVersion, stability, labelKeys, labelVals, statValueType) | ||||||||||
| if err != nil { | ||||||||||
|
|
@@ -1387,11 +1489,11 @@ func (d *DbStats) initCacheStats() error { | |||||||||
| if err != nil { | ||||||||||
| return err | ||||||||||
| } | ||||||||||
| resUtil.HighSeqCached, err = NewIntStat(SubsystemCacheKey, "high_seq_cached", StatUnitNoUnits, HighSeqCachedDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0) | ||||||||||
| resUtil.HighSeqCached, err = NewUIntStat(SubsystemCacheKey, "high_seq_cached", StatUnitNoUnits, HighSeqCachedDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0) | ||||||||||
| if err != nil { | ||||||||||
| return err | ||||||||||
| } | ||||||||||
| resUtil.HighSeqStable, err = NewIntStat(SubsystemCacheKey, "high_seq_stable", StatUnitNoUnits, HighStableSeqCachedDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0) | ||||||||||
| resUtil.HighSeqStable, err = NewUIntStat(SubsystemCacheKey, "high_seq_stable", StatUnitNoUnits, HighStableSeqCachedDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0) | ||||||||||
| if err != nil { | ||||||||||
| return err | ||||||||||
| } | ||||||||||
|
|
@@ -1684,11 +1786,11 @@ func (d *DbStats) initDatabaseStats() error { | |||||||||
| if err != nil { | ||||||||||
| return err | ||||||||||
| } | ||||||||||
| resUtil.CompactionAttachmentStartTime, err = NewIntStat(SubsystemDatabaseKey, "compaction_attachment_start_time", StatUnitUnixTimestamp, CompactionAttachmentStartTimeDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.GaugeValue, 0) | ||||||||||
| resUtil.CompactionAttachmentStartTime, err = NewUIntStat(SubsystemDatabaseKey, "compaction_attachment_start_time", StatUnitUnixTimestamp, CompactionAttachmentStartTimeDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.GaugeValue, 0) | ||||||||||
| if err != nil { | ||||||||||
| return err | ||||||||||
| } | ||||||||||
| resUtil.CompactionTombstoneStartTime, err = NewIntStat(SubsystemDatabaseKey, "compaction_tombstone_start_time", StatUnitUnixTimestamp, CompactionTombstoneStartTimeDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.GaugeValue, 0) | ||||||||||
| resUtil.CompactionTombstoneStartTime, err = NewUIntStat(SubsystemDatabaseKey, "compaction_tombstone_start_time", StatUnitUnixTimestamp, CompactionTombstoneStartTimeDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.GaugeValue, 0) | ||||||||||
| if err != nil { | ||||||||||
| return err | ||||||||||
| } | ||||||||||
|
|
@@ -1728,7 +1830,7 @@ func (d *DbStats) initDatabaseStats() error { | |||||||||
| if err != nil { | ||||||||||
| return err | ||||||||||
| } | ||||||||||
| resUtil.HighSeqFeed, err = NewIntStat(SubsystemDatabaseKey, "high_seq_feed", StatUnitNoUnits, HighSeqFeedDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0) | ||||||||||
| resUtil.HighSeqFeed, err = NewUIntStat(SubsystemDatabaseKey, "high_seq_feed", StatUnitNoUnits, HighSeqFeedDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0) | ||||||||||
| if err != nil { | ||||||||||
| return err | ||||||||||
| } | ||||||||||
|
|
@@ -1776,11 +1878,11 @@ func (d *DbStats) initDatabaseStats() error { | |||||||||
| if err != nil { | ||||||||||
| return err | ||||||||||
| } | ||||||||||
| resUtil.SequenceAssignedCount, err = NewIntStat(SubsystemDatabaseKey, "sequence_assigned_count", StatUnitNoUnits, SequenceAssignedCountDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0) | ||||||||||
| resUtil.SequenceAssignedCount, err = NewUIntStat(SubsystemDatabaseKey, "sequence_assigned_count", StatUnitNoUnits, SequenceAssignedCountDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0) | ||||||||||
| if err != nil { | ||||||||||
| return err | ||||||||||
| } | ||||||||||
| resUtil.LastSequenceAssignedValue, err = NewIntStat(SubsystemDatabaseKey, "last_sequence_assigned_value", StatUnitNoUnits, LastSequenceAssignedValueDesc, StatAddedVersion3dot2dot4, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0) | ||||||||||
| resUtil.LastSequenceAssignedValue, err = NewUIntStat(SubsystemDatabaseKey, "last_sequence_assigned_value", StatUnitNoUnits, LastSequenceAssignedValueDesc, StatAddedVersion3dot2dot4, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0) | ||||||||||
| if err != nil { | ||||||||||
| return err | ||||||||||
| } | ||||||||||
|
|
@@ -1792,15 +1894,15 @@ func (d *DbStats) initDatabaseStats() error { | |||||||||
| if err != nil { | ||||||||||
| return err | ||||||||||
| } | ||||||||||
| resUtil.SequenceReleasedCount, err = NewIntStat(SubsystemDatabaseKey, "sequence_released_count", StatUnitNoUnits, SequenceReleasedCountDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0) | ||||||||||
| resUtil.SequenceReleasedCount, err = NewUIntStat(SubsystemDatabaseKey, "sequence_released_count", StatUnitNoUnits, SequenceReleasedCountDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0) | ||||||||||
| if err != nil { | ||||||||||
| return err | ||||||||||
| } | ||||||||||
| resUtil.SequenceReservedCount, err = NewIntStat(SubsystemDatabaseKey, "sequence_reserved_count", StatUnitNoUnits, SequenceReservedCountDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0) | ||||||||||
| resUtil.SequenceReservedCount, err = NewUIntStat(SubsystemDatabaseKey, "sequence_reserved_count", StatUnitNoUnits, SequenceReservedCountDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0) | ||||||||||
| if err != nil { | ||||||||||
| return err | ||||||||||
| } | ||||||||||
| resUtil.LastSequenceReservedValue, err = NewIntStat(SubsystemDatabaseKey, "last_sequence_reserved_value", StatUnitNoUnits, LastSequenceReservedValueDesc, StatAddedVersion3dot2dot4, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0) | ||||||||||
| resUtil.LastSequenceReservedValue, err = NewUIntStat(SubsystemDatabaseKey, "last_sequence_reserved_value", StatUnitNoUnits, LastSequenceReservedValueDesc, StatAddedVersion3dot2dot4, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0) | ||||||||||
| if err != nil { | ||||||||||
| return err | ||||||||||
| } | ||||||||||
|
|
||||||||||
Uh oh!
There was an error while loading. Please reload this page.