@@ -72,7 +72,25 @@ struct TEvPrivate {
7272 };
7373};
7474
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+ };
7694
7795struct TAggQueryStat {
7896 NYql::TCounters::TEntry ReadBytes;
@@ -118,20 +136,22 @@ class TRowDispatcher : public TActorBootstrapped<TRowDispatcher> {
118136 };
119137
120138 struct TopicSessionKey {
139+ TString ReadGroup;
121140 TString Endpoint;
122141 TString Database;
123142 TString TopicPath;
124143 ui64 PartitionId;
125144
126145 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));
128148 hash = CombineHashes<ui64>(hash, std::hash<TString>()(Database));
129149 hash = CombineHashes<ui64>(hash, std::hash<TString>()(TopicPath));
130150 hash = CombineHashes<ui64>(hash, std::hash<ui64>()(PartitionId));
131151 return hash;
132152 }
133153 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
135155 && TopicPath == other.TopicPath && PartitionId == other.PartitionId ;
136156 }
137157 };
@@ -243,7 +263,7 @@ class TRowDispatcher : public TActorBootstrapped<TRowDispatcher> {
243263
244264 struct TAggregatedStats {
245265 NYql::TCounters::TEntry AllSessionsReadBytes;
246- TMap <TQueryStatKey, TMaybe<TAggQueryStat>> LastQueryStats;
266+ THashMap <TQueryStatKey, TMaybe<TAggQueryStat>, TQueryStatKeyHash > LastQueryStats;
247267 TDuration LastUpdateMetricsPeriod;
248268 };
249269
@@ -540,15 +560,14 @@ void TRowDispatcher::UpdateMetrics() {
540560 }
541561
542562 for (auto & [key, sessionsInfo] : TopicSessions) {
543- const auto & topic = key.TopicPath ;
544563 for (auto & [actorId, sessionInfo] : sessionsInfo.Sessions ) {
545564 auto read = NYql::TCounters::TEntry (sessionInfo.Stat .ReadBytes );
546565 AggrStats.AllSessionsReadBytes .Add (read);
547566 sessionInfo.AggrReadBytes = read;
548567 sessionInfo.Stat .Clear ();
549568
550569 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 }];
552571 if (!stat) {
553572 stat = TAggQueryStat ();
554573 }
@@ -557,22 +576,24 @@ void TRowDispatcher::UpdateMetrics() {
557576 }
558577 }
559578 }
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 ) {
562581 if (!stats) {
563- SetQueryMetrics (it->first , 0 , 0 , 0 );
564- it = AggrStats.LastQueryStats .erase (it);
582+ toDelete.insert (key);
565583 continue ;
566584 }
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);
569590 }
570591 PrintStateToLog ();
571592}
572593
573594void 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 ));
576597 topicGroup->GetCounter (" MaxUnreadBytes" )->Set (unreadBytesMax);
577598 topicGroup->GetCounter (" AvgUnreadBytes" )->Set (unreadBytesAvg);
578599 topicGroup->GetCounter (" MaxReadLag" )->Set (readLagMessagesMax);
@@ -608,16 +629,15 @@ TString TRowDispatcher::GetInternalState() {
608629 printDataRate (AggrStats.AllSessionsReadBytes );
609630 str << " \n " ;
610631
611- TMap <TQueryStatKey, TAggQueryStat> queryState;
612- TMap <TQueryStatKey, ui64> sessionCountByQuery;
632+ THashMap <TQueryStatKey, TAggQueryStat, TQueryStatKeyHash > queryState;
633+ THashMap <TQueryStatKey, ui64, TQueryStatKeyHash > sessionCountByQuery;
613634 ui64 unreadBytesSum = 0 ;
614635
615- for (auto & [key , sessionsInfo] : TopicSessions) {
636+ for (auto & [sessionKey , sessionsInfo] : TopicSessions) {
616637 for (auto & [actorId, sessionInfo] : sessionsInfo.Sessions ) {
617- const auto & topic = key.TopicPath ;
618638 unreadBytesSum += sessionInfo.Stat .UnreadBytes ;
619639 for (auto & [readActorId, consumer] : sessionInfo.Consumers ) {
620- auto key = TQueryStatKey{consumer->QueryId , topic };
640+ auto key = TQueryStatKey{consumer->QueryId , sessionKey. ReadGroup };
621641 ++sessionCountByQuery[key];
622642 queryState[key].Add (consumer->Stat );
623643 }
@@ -630,11 +650,11 @@ TString TRowDispatcher::GetInternalState() {
630650
631651 str << " Queries:\n " ;
632652 for (const auto & [queryStatKey, stat]: queryState) {
633- auto [queryId, topic ] = queryStatKey;
653+ auto [queryId, readGroup ] = queryStatKey;
634654 const auto & aggStat = AggrStats.LastQueryStats [queryStatKey];
635655 auto sessionsBufferSumSize = sessionCountByQuery[queryStatKey] * MaxSessionBufferSizeBytes;
636656 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" ;
638658 if (aggStat) {
639659 printDataRate (aggStat->ReadBytes );
640660 }
@@ -643,7 +663,7 @@ TString TRowDispatcher::GetInternalState() {
643663 }
644664 str << " TopicSessions:\n " ;
645665 for (auto & [key, sessionsInfo] : TopicSessions) {
646- str << " " << key.TopicPath << " / " << key.PartitionId ;
666+ str << " " << key.TopicPath << " / " << key.PartitionId << " / " << key. ReadGroup ;
647667 for (auto & [actorId, sessionInfo] : sessionsInfo.Sessions ) {
648668 str << " / " << LeftPad (actorId, 32 )
649669 << " data rate " << toHumanDR (sessionInfo.AggrReadBytes .Sum ) << " unread bytes " << toHuman (sessionInfo.Stat .UnreadBytes )
@@ -707,10 +727,10 @@ void TRowDispatcher::UpdateReadActorsInternalState() {
707727}
708728
709729void 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 () <<
711731 " 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 ()));
714734 topicGroup->GetCounter (" StartSession" , true )->Inc ();
715735
716736 NodesTracker.AddNode (ev->Sender .NodeId ());
@@ -733,7 +753,7 @@ void TRowDispatcher::Handle(NFq::TEvRowDispatcher::TEvStartSession::TPtr& ev) {
733753 }
734754 const auto & source = ev->Get ()->Record .GetSource ();
735755 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 ()};
737757 TopicSessionInfo& topicSessionInfo = TopicSessions[topicKey];
738758 Y_ENSURE (topicSessionInfo.Sessions .size () <= 1 );
739759
@@ -745,8 +765,10 @@ void TRowDispatcher::Handle(NFq::TEvRowDispatcher::TEvStartSession::TPtr& ev) {
745765 }
746766
747767 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);
749770 sessionActorId = ActorFactory->RegisterTopicSession (
771+ source.GetReadGroup (),
750772 source.GetTopicPath (),
751773 source.GetEndpoint (),
752774 source.GetDatabase (),
@@ -850,6 +872,7 @@ void TRowDispatcher::DeleteConsumer(const ConsumerSessionKey& key) {
850872 Send (new IEventHandle (consumerIt->second ->TopicSessionId , consumer->ReadActorId , event.release (), 0 ));
851873
852874 TopicSessionKey topicKey{
875+ consumer->SourceParams .GetReadGroup (),
853876 consumer->SourceParams .GetEndpoint (),
854877 consumer->SourceParams .GetDatabase (),
855878 consumer->SourceParams .GetTopicPath (),
@@ -879,7 +902,7 @@ void TRowDispatcher::Handle(const TEvPrivate::TEvTryConnect::TPtr& ev) {
879902void TRowDispatcher::Handle (const NYql::NDq::TEvRetryQueuePrivate::TEvEvHeartbeat::TPtr& ev) {
880903 auto it = ConsumersByEventQueueId.find (ev->Get ()->EventQueueId );
881904 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 );
883906 return ;
884907 }
885908 auto & sessionInfo = it->second ;
@@ -984,7 +1007,7 @@ void TRowDispatcher::Handle(const NMon::TEvHttpInfo::TPtr& ev) {
9841007void TRowDispatcher::Handle (NFq::TEvRowDispatcher::TEvSessionStatistic::TPtr& ev) {
9851008 LOG_ROW_DISPATCHER_TRACE (" TEvSessionStatistic from " << ev->Sender );
9861009 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 };
9881011
9891012 auto sessionsIt = TopicSessions.find (sessionKey);
9901013 if (sessionsIt == TopicSessions.end ()) {
0 commit comments