@@ -76,6 +76,7 @@ const (
7676 StatUnitUnixTimestamp = "unix timestamp"
7777
7878 StatFormatInt = "int"
79+ StatFormatUint = "uint64"
7980 StatFormatFloat = "float"
8081 StatFormatDuration = "duration"
8182 StatFormatBool = "bool"
@@ -472,10 +473,10 @@ type CacheStats struct {
472473 // The highest sequence number cached.
473474 //
474475 // There may be skipped sequences lower than high_seq_cached.
475- HighSeqCached * SgwIntStat `json:"high_seq_cached"`
476+ HighSeqCached * SgwUint64Stat `json:"high_seq_cached"`
476477 // The highest contiguous sequence number that has been cached.
477- HighSeqStable * SgwIntStat `json:"high_seq_stable"`
478- NonMobileIgnoredCount * SgwIntStat `json:"non_mobile_ignored_count"`
478+ HighSeqStable * SgwUint64Stat `json:"high_seq_stable"`
479+ NonMobileIgnoredCount * SgwIntStat `json:"non_mobile_ignored_count"`
479480 // The total number of active channels.
480481 NumActiveChannels * SgwIntStat `json:"num_active_channels"`
481482 // The total number of skipped sequences. This is a cumulative value.
@@ -606,9 +607,9 @@ type DatabaseStats struct {
606607 ReplicationBytesReceived * SgwIntStat `json:"replication_bytes_received"`
607608 ReplicationBytesSent * SgwIntStat `json:"replication_bytes_sent"`
608609 // The compaction_attachment_start_time.
609- CompactionAttachmentStartTime * SgwIntStat `json:"compaction_attachment_start_time"`
610+ CompactionAttachmentStartTime * SgwUint64Stat `json:"compaction_attachment_start_time"`
610611 // The compaction_tombstone_start_time.
611- CompactionTombstoneStartTime * SgwIntStat `json:"compaction_tombstone_start_time"`
612+ CompactionTombstoneStartTime * SgwUint64Stat `json:"compaction_tombstone_start_time"`
612613 // The total number of writes that left the document in a conflicted state. Includes new conflicts, and mutations that don’t resolve existing conflicts.
613614 ConflictWriteCount * SgwIntStat `json:"conflict_write_count"`
614615 // 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 {
630631 // The total size of xattrs written (in bytes).
631632 DocWritesXattrBytes * SgwIntStat `json:"doc_writes_xattr_bytes"`
632633 // Highest sequence number seen on the caching DCP feed.
633- HighSeqFeed * SgwIntStat `json:"high_seq_feed"`
634+ HighSeqFeed * SgwUint64Stat `json:"high_seq_feed"`
634635 // The number of attachments compacted
635636 NumAttachmentsCompacted * SgwIntStat `json:"num_attachments_compacted"`
636637 // The total number of documents read via Couchbase Lite 2.x replication since Sync Gateway node startup.
@@ -653,19 +654,19 @@ type DatabaseStats struct {
653654 // The total amount of bytes read over the public REST api
654655 PublicRestBytesRead * SgwIntStat `json:"public_rest_bytes_read"`
655656 // 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.
656- LastSequenceAssignedValue * SgwIntStat `json:"last_sequence_assigned_value"` // TODO: CBG-4579 - Replace with SgwUintStat stat
657+ LastSequenceAssignedValue * SgwUint64Stat `json:"last_sequence_assigned_value"`
657658 // The total number of sequence numbers assigned.
658- SequenceAssignedCount * SgwIntStat `json:"sequence_assigned_count"`
659+ SequenceAssignedCount * SgwUint64Stat `json:"sequence_assigned_count"`
659660 // The total number of high sequence lookups.
660661 SequenceGetCount * SgwIntStat `json:"sequence_get_count"`
661662 // The total number of times the sequence counter document has been incremented.
662663 SequenceIncrCount * SgwIntStat `json:"sequence_incr_count"`
663664 // The total number of unused, reserved sequences released by Sync Gateway.
664- SequenceReleasedCount * SgwIntStat `json:"sequence_released_count"`
665+ SequenceReleasedCount * SgwUint64Stat `json:"sequence_released_count"`
665666 // 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.
666- LastSequenceReservedValue * SgwIntStat `json:"last_sequence_reserved_value"` // TODO: CBG-4579 - Replace with SgwUintStat stat
667+ LastSequenceReservedValue * SgwUint64Stat `json:"last_sequence_reserved_value"`
667668 // The total number of sequences reserved by Sync Gateway.
668- SequenceReservedCount * SgwIntStat `json:"sequence_reserved_count"`
669+ SequenceReservedCount * SgwUint64Stat `json:"sequence_reserved_count"`
669670 // The total number of corrupt sequences above the MaxSequencesToRelease threshold seen at the sequence allocator
670671 CorruptSequenceCount * SgwIntStat `json:"corrupt_sequence_count"`
671672 // The total number of warnings relating to the channel name size.
@@ -986,6 +987,11 @@ type SgwIntStat struct {
986987 AtomicInt
987988}
988989
990+ type SgwUint64Stat struct {
991+ SgwStat
992+ atomic.Uint64
993+ }
994+
989995// uint64 is used here because atomic ints do not support floats. Floats are encoded to uint64
990996type SgwFloatStat struct {
991997 SgwStat
@@ -1079,6 +1085,74 @@ func (s *SgwIntStat) String() string {
10791085 return strconv .FormatInt (s .Value (), 10 )
10801086}
10811087
1088+ // NewUIntStat creates a uint64 stat. The stat is initialized to initialValue.
1089+ func NewUIntStat (subsystem , key , unit , description , addedVersion , deprecatedVersion , stability string , labelKeys , labelVals []string , statValueType prometheus.ValueType , initialValue uint64 ) (* SgwUint64Stat , error ) {
1090+ stat , err := newSGWStat (subsystem , key , unit , description , addedVersion , deprecatedVersion , stability , labelKeys , labelVals , statValueType )
1091+ if err != nil {
1092+ return nil , err
1093+ }
1094+
1095+ wrappedStat := & SgwUint64Stat {
1096+ SgwStat : * stat ,
1097+ }
1098+
1099+ wrappedStat .Set (initialValue )
1100+
1101+ if ! SkipPrometheusStatsRegistration {
1102+ err := prometheus .Register (wrappedStat )
1103+ if err != nil {
1104+ return nil , err
1105+ }
1106+ }
1107+
1108+ return wrappedStat , nil
1109+ }
1110+
1111+ // FormatString returns a name of the stat type used for generating documentation.
1112+ func (s * SgwUint64Stat ) FormatString () string {
1113+ return StatFormatUint
1114+ }
1115+
1116+ func (s * SgwUint64Stat ) Describe (ch chan <- * prometheus.Desc ) {
1117+ ch <- s .statDesc
1118+ }
1119+
1120+ // Collect satisfies the prometheus.Collector interface communicates the stat to prometheus. This is known to truncate to float64, which is the only format that prometheus can accept.
1121+ func (s * SgwUint64Stat ) Collect (ch chan <- prometheus.Metric ) {
1122+ ch <- prometheus .MustNewConstMetric (s .statDesc , s .statValueType , float64 (s .Value ()))
1123+ }
1124+
1125+ func (s * SgwUint64Stat ) MarshalJSON () ([]byte , error ) {
1126+ return []byte (strconv .FormatUint (s .Value (), 10 )), nil
1127+ }
1128+
1129+ func (s * SgwUint64Stat ) String () string {
1130+ return strconv .FormatUint (s .Value (), 10 )
1131+ }
1132+
1133+ // Set updates the existing value. This satisfies the AtomicUint interface but code can prefer SgwUint64Stat.Store to match atomic.Uint64.
1134+ func (s * SgwUint64Stat ) Set (value uint64 ) {
1135+ s .Store (value )
1136+ }
1137+
1138+ func (s * SgwUint64Stat ) SetIfMax (value uint64 ) {
1139+ for {
1140+ cur := s .Load ()
1141+ if cur >= value {
1142+ return
1143+ }
1144+
1145+ if s .CompareAndSwap (cur , value ) {
1146+ return
1147+ }
1148+ }
1149+ }
1150+
1151+ // Value returns the value. This satisfies the AtomicUint interface but new code should prefer SgwUint64Stat.Load to match atomic.Uint64 interface.
1152+ func (s * SgwUint64Stat ) Value () uint64 {
1153+ return s .Load ()
1154+ }
1155+
10821156func NewFloatStat (subsystem , key , unit , description , addedVersion , deprecatedVersion , stability string , labelKeys , labelVals []string , statValueType prometheus.ValueType , initialValue float64 ) (* SgwFloatStat , error ) {
10831157 stat , err := newSGWStat (subsystem , key , unit , description , addedVersion , deprecatedVersion , stability , labelKeys , labelVals , statValueType )
10841158 if err != nil {
@@ -1387,11 +1461,11 @@ func (d *DbStats) initCacheStats() error {
13871461 if err != nil {
13881462 return err
13891463 }
1390- resUtil .HighSeqCached , err = NewIntStat (SubsystemCacheKey , "high_seq_cached" , StatUnitNoUnits , HighSeqCachedDesc , StatAddedVersion3dot0dot0 , StatDeprecatedVersionNotDeprecated , StatStabilityCommitted , labelKeys , labelVals , prometheus .CounterValue , 0 )
1464+ resUtil .HighSeqCached , err = NewUIntStat (SubsystemCacheKey , "high_seq_cached" , StatUnitNoUnits , HighSeqCachedDesc , StatAddedVersion3dot0dot0 , StatDeprecatedVersionNotDeprecated , StatStabilityCommitted , labelKeys , labelVals , prometheus .CounterValue , 0 )
13911465 if err != nil {
13921466 return err
13931467 }
1394- resUtil .HighSeqStable , err = NewIntStat (SubsystemCacheKey , "high_seq_stable" , StatUnitNoUnits , HighStableSeqCachedDesc , StatAddedVersion3dot0dot0 , StatDeprecatedVersionNotDeprecated , StatStabilityCommitted , labelKeys , labelVals , prometheus .CounterValue , 0 )
1468+ resUtil .HighSeqStable , err = NewUIntStat (SubsystemCacheKey , "high_seq_stable" , StatUnitNoUnits , HighStableSeqCachedDesc , StatAddedVersion3dot0dot0 , StatDeprecatedVersionNotDeprecated , StatStabilityCommitted , labelKeys , labelVals , prometheus .CounterValue , 0 )
13951469 if err != nil {
13961470 return err
13971471 }
@@ -1684,11 +1758,11 @@ func (d *DbStats) initDatabaseStats() error {
16841758 if err != nil {
16851759 return err
16861760 }
1687- resUtil .CompactionAttachmentStartTime , err = NewIntStat (SubsystemDatabaseKey , "compaction_attachment_start_time" , StatUnitUnixTimestamp , CompactionAttachmentStartTimeDesc , StatAddedVersion3dot0dot0 , StatDeprecatedVersionNotDeprecated , StatStabilityCommitted , labelKeys , labelVals , prometheus .GaugeValue , 0 )
1761+ resUtil .CompactionAttachmentStartTime , err = NewUIntStat (SubsystemDatabaseKey , "compaction_attachment_start_time" , StatUnitUnixTimestamp , CompactionAttachmentStartTimeDesc , StatAddedVersion3dot0dot0 , StatDeprecatedVersionNotDeprecated , StatStabilityCommitted , labelKeys , labelVals , prometheus .GaugeValue , 0 )
16881762 if err != nil {
16891763 return err
16901764 }
1691- resUtil .CompactionTombstoneStartTime , err = NewIntStat (SubsystemDatabaseKey , "compaction_tombstone_start_time" , StatUnitUnixTimestamp , CompactionTombstoneStartTimeDesc , StatAddedVersion3dot0dot0 , StatDeprecatedVersionNotDeprecated , StatStabilityCommitted , labelKeys , labelVals , prometheus .GaugeValue , 0 )
1765+ resUtil .CompactionTombstoneStartTime , err = NewUIntStat (SubsystemDatabaseKey , "compaction_tombstone_start_time" , StatUnitUnixTimestamp , CompactionTombstoneStartTimeDesc , StatAddedVersion3dot0dot0 , StatDeprecatedVersionNotDeprecated , StatStabilityCommitted , labelKeys , labelVals , prometheus .GaugeValue , 0 )
16921766 if err != nil {
16931767 return err
16941768 }
@@ -1728,7 +1802,7 @@ func (d *DbStats) initDatabaseStats() error {
17281802 if err != nil {
17291803 return err
17301804 }
1731- resUtil .HighSeqFeed , err = NewIntStat (SubsystemDatabaseKey , "high_seq_feed" , StatUnitNoUnits , HighSeqFeedDesc , StatAddedVersion3dot0dot0 , StatDeprecatedVersionNotDeprecated , StatStabilityCommitted , labelKeys , labelVals , prometheus .CounterValue , 0 )
1805+ resUtil .HighSeqFeed , err = NewUIntStat (SubsystemDatabaseKey , "high_seq_feed" , StatUnitNoUnits , HighSeqFeedDesc , StatAddedVersion3dot0dot0 , StatDeprecatedVersionNotDeprecated , StatStabilityCommitted , labelKeys , labelVals , prometheus .CounterValue , 0 )
17321806 if err != nil {
17331807 return err
17341808 }
@@ -1776,11 +1850,11 @@ func (d *DbStats) initDatabaseStats() error {
17761850 if err != nil {
17771851 return err
17781852 }
1779- resUtil .SequenceAssignedCount , err = NewIntStat (SubsystemDatabaseKey , "sequence_assigned_count" , StatUnitNoUnits , SequenceAssignedCountDesc , StatAddedVersion3dot0dot0 , StatDeprecatedVersionNotDeprecated , StatStabilityCommitted , labelKeys , labelVals , prometheus .CounterValue , 0 )
1853+ resUtil .SequenceAssignedCount , err = NewUIntStat (SubsystemDatabaseKey , "sequence_assigned_count" , StatUnitNoUnits , SequenceAssignedCountDesc , StatAddedVersion3dot0dot0 , StatDeprecatedVersionNotDeprecated , StatStabilityCommitted , labelKeys , labelVals , prometheus .CounterValue , 0 )
17801854 if err != nil {
17811855 return err
17821856 }
1783- resUtil .LastSequenceAssignedValue , err = NewIntStat (SubsystemDatabaseKey , "last_sequence_assigned_value" , StatUnitNoUnits , LastSequenceAssignedValueDesc , StatAddedVersion3dot2dot4 , StatDeprecatedVersionNotDeprecated , StatStabilityCommitted , labelKeys , labelVals , prometheus .CounterValue , 0 )
1857+ resUtil .LastSequenceAssignedValue , err = NewUIntStat (SubsystemDatabaseKey , "last_sequence_assigned_value" , StatUnitNoUnits , LastSequenceAssignedValueDesc , StatAddedVersion3dot2dot4 , StatDeprecatedVersionNotDeprecated , StatStabilityCommitted , labelKeys , labelVals , prometheus .CounterValue , 0 )
17841858 if err != nil {
17851859 return err
17861860 }
@@ -1792,15 +1866,15 @@ func (d *DbStats) initDatabaseStats() error {
17921866 if err != nil {
17931867 return err
17941868 }
1795- resUtil .SequenceReleasedCount , err = NewIntStat (SubsystemDatabaseKey , "sequence_released_count" , StatUnitNoUnits , SequenceReleasedCountDesc , StatAddedVersion3dot0dot0 , StatDeprecatedVersionNotDeprecated , StatStabilityCommitted , labelKeys , labelVals , prometheus .CounterValue , 0 )
1869+ resUtil .SequenceReleasedCount , err = NewUIntStat (SubsystemDatabaseKey , "sequence_released_count" , StatUnitNoUnits , SequenceReleasedCountDesc , StatAddedVersion3dot0dot0 , StatDeprecatedVersionNotDeprecated , StatStabilityCommitted , labelKeys , labelVals , prometheus .CounterValue , 0 )
17961870 if err != nil {
17971871 return err
17981872 }
1799- resUtil .SequenceReservedCount , err = NewIntStat (SubsystemDatabaseKey , "sequence_reserved_count" , StatUnitNoUnits , SequenceReservedCountDesc , StatAddedVersion3dot0dot0 , StatDeprecatedVersionNotDeprecated , StatStabilityCommitted , labelKeys , labelVals , prometheus .CounterValue , 0 )
1873+ resUtil .SequenceReservedCount , err = NewUIntStat (SubsystemDatabaseKey , "sequence_reserved_count" , StatUnitNoUnits , SequenceReservedCountDesc , StatAddedVersion3dot0dot0 , StatDeprecatedVersionNotDeprecated , StatStabilityCommitted , labelKeys , labelVals , prometheus .CounterValue , 0 )
18001874 if err != nil {
18011875 return err
18021876 }
1803- resUtil .LastSequenceReservedValue , err = NewIntStat (SubsystemDatabaseKey , "last_sequence_reserved_value" , StatUnitNoUnits , LastSequenceReservedValueDesc , StatAddedVersion3dot2dot4 , StatDeprecatedVersionNotDeprecated , StatStabilityCommitted , labelKeys , labelVals , prometheus .CounterValue , 0 )
1877+ resUtil .LastSequenceReservedValue , err = NewUIntStat (SubsystemDatabaseKey , "last_sequence_reserved_value" , StatUnitNoUnits , LastSequenceReservedValueDesc , StatAddedVersion3dot2dot4 , StatDeprecatedVersionNotDeprecated , StatStabilityCommitted , labelKeys , labelVals , prometheus .CounterValue , 0 )
18041878 if err != nil {
18051879 return err
18061880 }
0 commit comments