@@ -13,6 +13,10 @@ type OffsetStorage struct {
1313 consumerOffsetCh chan * kafka.StorageRequest
1414 clusterCh chan * kafka.StorageRequest
1515
16+ notReadyPartitionConsumers int32
17+ offsetTopicConsumed bool
18+
19+ consumerStatusLock sync.RWMutex // Lock is being used if you either access notReadyPartitionConsumers or offsetTopicConsumed
1620 consumerOffsetsLock sync.RWMutex
1721 partitionHighWaterMarksLock sync.RWMutex
1822 partitionLowWaterMarksLock sync.RWMutex
@@ -22,6 +26,8 @@ type OffsetStorage struct {
2226 consumerOffsets map [string ]ConsumerPartitionOffsetMetric
2327 partitionHighWaterMarks map [string ]kafka.PartitionWaterMark
2428 partitionLowWaterMarks map [string ]kafka.PartitionWaterMark
29+
30+ logger * log.Entry
2531}
2632
2733// ConsumerPartitionOffsetMetric represents an offset commit but is extended by further fields which can be
@@ -41,13 +47,20 @@ func NewOffsetStorage(consumerOffsetCh chan *kafka.StorageRequest, clusterCh cha
4147 consumerOffsetCh : consumerOffsetCh ,
4248 clusterCh : clusterCh ,
4349
50+ notReadyPartitionConsumers : 0 ,
51+ offsetTopicConsumed : false ,
52+
4453 consumerOffsetsLock : sync.RWMutex {},
4554 partitionHighWaterMarksLock : sync.RWMutex {},
4655 partitionLowWaterMarksLock : sync.RWMutex {},
4756
4857 consumerOffsets : make (map [string ]ConsumerPartitionOffsetMetric ),
4958 partitionHighWaterMarks : make (map [string ]kafka.PartitionWaterMark ),
5059 partitionLowWaterMarks : make (map [string ]kafka.PartitionWaterMark ),
60+
61+ logger : log .WithFields (log.Fields {
62+ "module" : "storage" ,
63+ }),
5164 }
5265}
5366
@@ -64,6 +77,11 @@ func (module *OffsetStorage) consumerOffsetWorker() {
6477 module .storeOffsetEntry (request .ConsumerOffset )
6578 case kafka .StorageDeleteConsumerGroup :
6679 module .deleteOffsetEntry (request .ConsumerGroupName , request .TopicName , request .PartitionID )
80+ case kafka .StorageRegisterOffsetPartition :
81+ module .registerOffsetPartition (request .PartitionID )
82+ case kafka .StorageMarkOffsetPartitionReady :
83+ module .markOffsetPartitionReady (request .PartitionID )
84+
6785 default :
6886 log .WithFields (log.Fields {
6987 "request_type" : request .RequestType ,
@@ -98,6 +116,24 @@ func (module *OffsetStorage) storePartitionHighWaterMark(offset *kafka.Partition
98116 module .partitionHighWaterMarksLock .Unlock ()
99117}
100118
119+ func (module * OffsetStorage ) registerOffsetPartition (partitionID int32 ) {
120+ module .consumerOffsetsLock .Lock ()
121+ defer module .consumerOffsetsLock .Unlock ()
122+
123+ module .notReadyPartitionConsumers ++
124+ }
125+
126+ func (module * OffsetStorage ) markOffsetPartitionReady (partitionID int32 ) {
127+ module .consumerOffsetsLock .Lock ()
128+ defer module .consumerOffsetsLock .Unlock ()
129+
130+ module .notReadyPartitionConsumers --
131+ if module .notReadyPartitionConsumers == 0 {
132+ module .logger .Info ("Offset topic has been consumed" )
133+ module .offsetTopicConsumed = true
134+ }
135+ }
136+
101137func (module * OffsetStorage ) storePartitionLowWaterMark (offset * kafka.PartitionWaterMark ) {
102138 key := fmt .Sprintf ("%v:%v" , offset .TopicName , offset .PartitionID )
103139 module .partitionLowWaterMarksLock .Lock ()
@@ -170,3 +206,12 @@ func (module *OffsetStorage) PartitionLowWaterMarks() map[string]kafka.Partition
170206
171207 return mapCopy
172208}
209+
210+ // IsConsumed indicates whether the consumer offsets topic lag has been caught up and therefore
211+ // the metrics reported by this module are accurate or not
212+ func (module * OffsetStorage ) IsConsumed () bool {
213+ module .consumerStatusLock .RLock ()
214+ defer module .consumerStatusLock .RUnlock ()
215+
216+ return module .offsetTopicConsumed
217+ }
0 commit comments