@@ -72,7 +72,25 @@ struct TEvPrivate {
72
72
};
73
73
};
74
74
75
- using TQueryStatKey = std::pair<TString, TString>; // QueryId / Topic
75
+ struct TQueryStatKey {
76
+ TString QueryId;
77
+ TString ReadGroup;
78
+
79
+ size_t Hash () const noexcept {
80
+ ui64 hash = std::hash<TString>()(QueryId);
81
+ hash = CombineHashes<ui64>(hash, std::hash<TString>()(ReadGroup));
82
+ return hash;
83
+ }
84
+ bool operator ==(const TQueryStatKey& other) const {
85
+ return QueryId == other.QueryId && ReadGroup == other.ReadGroup ;
86
+ }
87
+ };
88
+
89
+ struct TQueryStatKeyHash {
90
+ size_t operator ()(const TQueryStatKey& k) const {
91
+ return k.Hash ();
92
+ }
93
+ };
76
94
77
95
struct TAggQueryStat {
78
96
NYql::TCounters::TEntry ReadBytes;
@@ -118,20 +136,22 @@ class TRowDispatcher : public TActorBootstrapped<TRowDispatcher> {
118
136
};
119
137
120
138
struct TopicSessionKey {
139
+ TString ReadGroup;
121
140
TString Endpoint;
122
141
TString Database;
123
142
TString TopicPath;
124
143
ui64 PartitionId;
125
144
126
145
size_t Hash () const noexcept {
127
- ui64 hash = std::hash<TString>()(Endpoint);
146
+ ui64 hash = std::hash<TString>()(ReadGroup);
147
+ hash = CombineHashes<ui64>(hash, std::hash<TString>()(Endpoint));
128
148
hash = CombineHashes<ui64>(hash, std::hash<TString>()(Database));
129
149
hash = CombineHashes<ui64>(hash, std::hash<TString>()(TopicPath));
130
150
hash = CombineHashes<ui64>(hash, std::hash<ui64>()(PartitionId));
131
151
return hash;
132
152
}
133
153
bool operator ==(const TopicSessionKey& other) const {
134
- return Endpoint == other.Endpoint && Database == other.Database
154
+ return ReadGroup == other. ReadGroup && Endpoint == other.Endpoint && Database == other.Database
135
155
&& TopicPath == other.TopicPath && PartitionId == other.PartitionId ;
136
156
}
137
157
};
@@ -243,7 +263,7 @@ class TRowDispatcher : public TActorBootstrapped<TRowDispatcher> {
243
263
244
264
struct TAggregatedStats {
245
265
NYql::TCounters::TEntry AllSessionsReadBytes;
246
- TMap <TQueryStatKey, TMaybe<TAggQueryStat>> LastQueryStats;
266
+ THashMap <TQueryStatKey, TMaybe<TAggQueryStat>, TQueryStatKeyHash > LastQueryStats;
247
267
TDuration LastUpdateMetricsPeriod;
248
268
};
249
269
@@ -540,15 +560,14 @@ void TRowDispatcher::UpdateMetrics() {
540
560
}
541
561
542
562
for (auto & [key, sessionsInfo] : TopicSessions) {
543
- const auto & topic = key.TopicPath ;
544
563
for (auto & [actorId, sessionInfo] : sessionsInfo.Sessions ) {
545
564
auto read = NYql::TCounters::TEntry (sessionInfo.Stat .ReadBytes );
546
565
AggrStats.AllSessionsReadBytes .Add (read);
547
566
sessionInfo.AggrReadBytes = read;
548
567
sessionInfo.Stat .Clear ();
549
568
550
569
for (auto & [readActorId, consumer] : sessionInfo.Consumers ) {
551
- auto & stat = AggrStats.LastQueryStats [TQueryStatKey{consumer->QueryId , topic }];
570
+ auto & stat = AggrStats.LastQueryStats [TQueryStatKey{consumer->QueryId , key. ReadGroup }];
552
571
if (!stat) {
553
572
stat = TAggQueryStat ();
554
573
}
@@ -557,22 +576,24 @@ void TRowDispatcher::UpdateMetrics() {
557
576
}
558
577
}
559
578
}
560
- for ( auto it = AggrStats. LastQueryStats . begin (); it != AggrStats. LastQueryStats . end ();) {
561
- const auto & stats = it-> second ;
579
+ THashSet<TQueryStatKey, TQueryStatKeyHash> toDelete;
580
+ for ( const auto & [key, stats] : AggrStats. LastQueryStats ) {
562
581
if (!stats) {
563
- SetQueryMetrics (it->first , 0 , 0 , 0 );
564
- it = AggrStats.LastQueryStats .erase (it);
582
+ toDelete.insert (key);
565
583
continue ;
566
584
}
567
- SetQueryMetrics (it->first , stats->UnreadBytes .Max , stats->UnreadBytes .Avg , stats->ReadLagMessages .Max );
568
- ++it;
585
+ SetQueryMetrics (key, stats->UnreadBytes .Max , stats->UnreadBytes .Avg , stats->ReadLagMessages .Max );
586
+ }
587
+ for (const auto & key : toDelete) {
588
+ SetQueryMetrics (key, 0 , 0 , 0 );
589
+ AggrStats.LastQueryStats .erase (key);
569
590
}
570
591
PrintStateToLog ();
571
592
}
572
593
573
594
void TRowDispatcher::SetQueryMetrics (const TQueryStatKey& queryKey, ui64 unreadBytesMax, ui64 unreadBytesAvg, i64 readLagMessagesMax) {
574
- auto queryGroup = Metrics.Counters ->GetSubgroup (" queryId " , queryKey.first );
575
- auto topicGroup = queryGroup->GetSubgroup (" topic " , CleanupCounterValueString (queryKey.second ));
595
+ auto queryGroup = Metrics.Counters ->GetSubgroup (" query_id " , queryKey.QueryId );
596
+ auto topicGroup = queryGroup->GetSubgroup (" read_group " , CleanupCounterValueString (queryKey.ReadGroup ));
576
597
topicGroup->GetCounter (" MaxUnreadBytes" )->Set (unreadBytesMax);
577
598
topicGroup->GetCounter (" AvgUnreadBytes" )->Set (unreadBytesAvg);
578
599
topicGroup->GetCounter (" MaxReadLag" )->Set (readLagMessagesMax);
@@ -608,16 +629,15 @@ TString TRowDispatcher::GetInternalState() {
608
629
printDataRate (AggrStats.AllSessionsReadBytes );
609
630
str << " \n " ;
610
631
611
- TMap <TQueryStatKey, TAggQueryStat> queryState;
612
- TMap <TQueryStatKey, ui64> sessionCountByQuery;
632
+ THashMap <TQueryStatKey, TAggQueryStat, TQueryStatKeyHash > queryState;
633
+ THashMap <TQueryStatKey, ui64, TQueryStatKeyHash > sessionCountByQuery;
613
634
ui64 unreadBytesSum = 0 ;
614
635
615
- for (auto & [key , sessionsInfo] : TopicSessions) {
636
+ for (auto & [sessionKey , sessionsInfo] : TopicSessions) {
616
637
for (auto & [actorId, sessionInfo] : sessionsInfo.Sessions ) {
617
- const auto & topic = key.TopicPath ;
618
638
unreadBytesSum += sessionInfo.Stat .UnreadBytes ;
619
639
for (auto & [readActorId, consumer] : sessionInfo.Consumers ) {
620
- auto key = TQueryStatKey{consumer->QueryId , topic };
640
+ auto key = TQueryStatKey{consumer->QueryId , sessionKey. ReadGroup };
621
641
++sessionCountByQuery[key];
622
642
queryState[key].Add (consumer->Stat );
623
643
}
@@ -630,11 +650,11 @@ TString TRowDispatcher::GetInternalState() {
630
650
631
651
str << " Queries:\n " ;
632
652
for (const auto & [queryStatKey, stat]: queryState) {
633
- auto [queryId, topic ] = queryStatKey;
653
+ auto [queryId, readGroup ] = queryStatKey;
634
654
const auto & aggStat = AggrStats.LastQueryStats [queryStatKey];
635
655
auto sessionsBufferSumSize = sessionCountByQuery[queryStatKey] * MaxSessionBufferSizeBytes;
636
656
auto used = sessionsBufferSumSize ? (stat.UnreadBytes .Sum * 100.0 / sessionsBufferSumSize) : 0.0 ;
637
- str << " " << queryId << " / " << topic << " : buffer used (all partitions) " << LeftPad (Prec (used, 4 ), 10 ) << " % (" << toHuman (stat.UnreadBytes .Sum ) << " ) unread max (one partition) " << toHuman (stat.UnreadBytes .Max ) << " data rate" ;
657
+ str << " " << queryId << " / " << readGroup << " : buffer used (all partitions) " << LeftPad (Prec (used, 4 ), 10 ) << " % (" << toHuman (stat.UnreadBytes .Sum ) << " ) unread max (one partition) " << toHuman (stat.UnreadBytes .Max ) << " data rate" ;
638
658
if (aggStat) {
639
659
printDataRate (aggStat->ReadBytes );
640
660
}
@@ -643,7 +663,7 @@ TString TRowDispatcher::GetInternalState() {
643
663
}
644
664
str << " TopicSessions:\n " ;
645
665
for (auto & [key, sessionsInfo] : TopicSessions) {
646
- str << " " << key.TopicPath << " / " << key.PartitionId ;
666
+ str << " " << key.TopicPath << " / " << key.PartitionId << " / " << key. ReadGroup ;
647
667
for (auto & [actorId, sessionInfo] : sessionsInfo.Sessions ) {
648
668
str << " / " << LeftPad (actorId, 32 )
649
669
<< " data rate " << toHumanDR (sessionInfo.AggrReadBytes .Sum ) << " unread bytes " << toHuman (sessionInfo.Stat .UnreadBytes )
@@ -707,10 +727,10 @@ void TRowDispatcher::UpdateReadActorsInternalState() {
707
727
}
708
728
709
729
void TRowDispatcher::Handle (NFq::TEvRowDispatcher::TEvStartSession::TPtr& ev) {
710
- LOG_ROW_DISPATCHER_DEBUG (" Received TEvStartSession from " << ev->Sender << " , topicPath " << ev->Get ()->Record .GetSource ().GetTopicPath () <<
730
+ LOG_ROW_DISPATCHER_DEBUG (" Received TEvStartSession from " << ev->Sender << " , read group " << ev-> Get ()-> Record . GetSource (). GetReadGroup () << " , topicPath " << ev->Get ()->Record .GetSource ().GetTopicPath () <<
711
731
" part id " << ev->Get ()->Record .GetPartitionId () << " query id " << ev->Get ()->Record .GetQueryId () << " cookie " << ev->Cookie );
712
- auto queryGroup = Metrics.Counters ->GetSubgroup (" queryId " , ev->Get ()->Record .GetQueryId ());
713
- auto topicGroup = queryGroup->GetSubgroup (" topic " , CleanupCounterValueString (ev->Get ()->Record .GetSource ().GetTopicPath ()));
732
+ auto queryGroup = Metrics.Counters ->GetSubgroup (" query_id " , ev->Get ()->Record .GetQueryId ());
733
+ auto topicGroup = queryGroup->GetSubgroup (" read_group " , CleanupCounterValueString (ev->Get ()->Record .GetSource ().GetReadGroup ()));
714
734
topicGroup->GetCounter (" StartSession" , true )->Inc ();
715
735
716
736
NodesTracker.AddNode (ev->Sender .NodeId ());
@@ -733,7 +753,7 @@ void TRowDispatcher::Handle(NFq::TEvRowDispatcher::TEvStartSession::TPtr& ev) {
733
753
}
734
754
const auto & source = ev->Get ()->Record .GetSource ();
735
755
TActorId sessionActorId;
736
- TopicSessionKey topicKey{source.GetEndpoint (), source.GetDatabase (), source.GetTopicPath (), ev->Get ()->Record .GetPartitionId ()};
756
+ TopicSessionKey topicKey{source.GetReadGroup (), source. GetEndpoint (), source.GetDatabase (), source.GetTopicPath (), ev->Get ()->Record .GetPartitionId ()};
737
757
TopicSessionInfo& topicSessionInfo = TopicSessions[topicKey];
738
758
Y_ENSURE (topicSessionInfo.Sessions .size () <= 1 );
739
759
@@ -745,8 +765,10 @@ void TRowDispatcher::Handle(NFq::TEvRowDispatcher::TEvStartSession::TPtr& ev) {
745
765
}
746
766
747
767
if (topicSessionInfo.Sessions .empty ()) {
748
- LOG_ROW_DISPATCHER_DEBUG (" Create new session, offset " << readOffset);
768
+ LOG_ROW_DISPATCHER_DEBUG (" Create new session: read group " << source.GetReadGroup () << " topic " << source.GetTopicPath ()
769
+ << " part id " << ev->Get ()->Record .GetPartitionId () << " offset " << readOffset);
749
770
sessionActorId = ActorFactory->RegisterTopicSession (
771
+ source.GetReadGroup (),
750
772
source.GetTopicPath (),
751
773
source.GetEndpoint (),
752
774
source.GetDatabase (),
@@ -850,6 +872,7 @@ void TRowDispatcher::DeleteConsumer(const ConsumerSessionKey& key) {
850
872
Send (new IEventHandle (consumerIt->second ->TopicSessionId , consumer->ReadActorId , event.release (), 0 ));
851
873
852
874
TopicSessionKey topicKey{
875
+ consumer->SourceParams .GetReadGroup (),
853
876
consumer->SourceParams .GetEndpoint (),
854
877
consumer->SourceParams .GetDatabase (),
855
878
consumer->SourceParams .GetTopicPath (),
@@ -879,7 +902,7 @@ void TRowDispatcher::Handle(const TEvPrivate::TEvTryConnect::TPtr& ev) {
879
902
void TRowDispatcher::Handle (const NYql::NDq::TEvRetryQueuePrivate::TEvEvHeartbeat::TPtr& ev) {
880
903
auto it = ConsumersByEventQueueId.find (ev->Get ()->EventQueueId );
881
904
if (it == ConsumersByEventQueueId.end ()) {
882
- LOG_ROW_DISPATCHER_WARN (" No consumer with EventQueueId = " << ev->Get ()->EventQueueId );
905
+ LOG_ROW_DISPATCHER_TRACE (" No consumer with EventQueueId = " << ev->Get ()->EventQueueId );
883
906
return ;
884
907
}
885
908
auto & sessionInfo = it->second ;
@@ -984,7 +1007,7 @@ void TRowDispatcher::Handle(const NMon::TEvHttpInfo::TPtr& ev) {
984
1007
void TRowDispatcher::Handle (NFq::TEvRowDispatcher::TEvSessionStatistic::TPtr& ev) {
985
1008
LOG_ROW_DISPATCHER_TRACE (" TEvSessionStatistic from " << ev->Sender );
986
1009
const auto & key = ev->Get ()->Stat .SessionKey ;
987
- TopicSessionKey sessionKey{key.Endpoint , key.Database , key.TopicPath , key.PartitionId };
1010
+ TopicSessionKey sessionKey{key.ReadGroup , key. Endpoint , key.Database , key.TopicPath , key.PartitionId };
988
1011
989
1012
auto sessionsIt = TopicSessions.find (sessionKey);
990
1013
if (sessionsIt == TopicSessions.end ()) {
0 commit comments