@@ -8,6 +8,7 @@ package status
88import (
99 "bytes"
1010 "context"
11+ "fmt"
1112 "io"
1213 "math/rand"
1314 "os"
@@ -264,6 +265,9 @@ func TestMetricsRecorderLabels(t *testing.T) {
264265 // Verify that GetTimeSeriesData with includeChildMetrics=true returns child labels
265266 // ========================================
266267
268+ // Enable the cluster setting for child metrics storage
269+ ChildMetricsStorageEnabled .Override (context .Background (), & st .SV , true )
270+
267271 // Add aggmetrics with child labels to the app registry
268272 aggCounter := aggmetric .NewCounter (
269273 metric.Metadata {
@@ -315,92 +319,100 @@ func TestMetricsRecorderLabels(t *testing.T) {
315319 child6 .RecordValue (400 )
316320 child6 .RecordValue (500 )
317321
318- // Enable the cluster setting for child metrics storage
319- ChildMetricsStorageEnabled .Override (context .Background (), & st .SV , true )
320-
321322 // Get time series data with child metrics enabled
322323 childData := recorder .GetTimeSeriesData (true )
323324
324- var foundCounterFeedA123 bool
325- var foundCounterFeedB456 bool
326- var foundGaugeMineActive bool
327- var foundGaugeYoursPaused bool
328- var foundHistogramDefaultCount bool
329- var foundHistogramUserCount bool
330- var foundHistogramDefaultAvg bool
331- var foundHistogramUserAvg bool
332-
333- for _ , ts := range childData {
334- // Check for changefeed.emitted_messages with some_id and feed_id labels
335- if strings .Contains (ts .Name , "cr.node.changefeed.emitted_messages" ) {
336- if strings .Contains (ts .Name , "feed_id=\" feed-a\" " ) && strings .Contains (ts .Name , "some_id=\" 123\" " ) {
337- foundCounterFeedA123 = true
338- require .Equal (t , "7" , ts .Source , "Expected source to be node ID 7" )
339- require .Len (t , ts .Datapoints , 1 )
340- require .Equal (t , float64 (100 ), ts .Datapoints [0 ].Value )
341- }
342- if strings .Contains (ts .Name , "feed_id=\" feed-b\" " ) && strings .Contains (ts .Name , "some_id=\" 456\" " ) {
343- foundCounterFeedB456 = true
344- require .Equal (t , "7" , ts .Source , "Expected source to be node ID 7" )
345- require .Len (t , ts .Datapoints , 1 )
346- require .Equal (t , float64 (200 ), ts .Datapoints [0 ].Value )
347- }
348- }
349-
350- // Check for changefeed.lagging_ranges with db and status labels
351- if strings .Contains (ts .Name , "cr.node.changefeed.lagging_ranges" ) {
352- if strings .Contains (ts .Name , "db=\" mine\" " ) && strings .Contains (ts .Name , "status__=\" active\" " ) {
353- foundGaugeMineActive = true
354- require .Equal (t , "7" , ts .Source , "Expected source to be node ID 7" )
355- require .Len (t , ts .Datapoints , 1 )
356- require .Equal (t , float64 (1 ), ts .Datapoints [0 ].Value )
357- }
358- if strings .Contains (ts .Name , "db=\" yours\" " ) && strings .Contains (ts .Name , "status__=\" paused\" " ) {
359- foundGaugeYoursPaused = true
360- require .Equal (t , "7" , ts .Source , "Expected source to be node ID 7" )
361- require .Len (t , ts .Datapoints , 1 )
362- require .Equal (t , float64 (0 ), ts .Datapoints [0 ].Value )
363- }
364- }
325+ // Define test cases for app metrics
326+ appMetricTestCases := []struct {
327+ name string
328+ metricPrefix string
329+ labelMatchers []string
330+ expectedSource string
331+ expectedValue float64
332+ }{
333+ {
334+ name : "counter feed-a with some_id=123" ,
335+ metricPrefix : "cr.node.changefeed.emitted_messages" ,
336+ labelMatchers : []string {"feed_id=\" feed-a\" " , "some_id=\" 123\" " },
337+ expectedSource : "7" ,
338+ expectedValue : 100 ,
339+ },
340+ {
341+ name : "counter feed-b with some_id=456" ,
342+ metricPrefix : "cr.node.changefeed.emitted_messages" ,
343+ labelMatchers : []string {"feed_id=\" feed-b\" " , "some_id=\" 456\" " },
344+ expectedSource : "7" ,
345+ expectedValue : 200 ,
346+ },
347+ {
348+ name : "gauge mine with status=active" ,
349+ metricPrefix : "cr.node.changefeed.lagging_ranges" ,
350+ labelMatchers : []string {"db=\" mine\" " , "status__=\" active\" " },
351+ expectedSource : "7" ,
352+ expectedValue : 1 ,
353+ },
354+ {
355+ name : "gauge yours with status=paused" ,
356+ metricPrefix : "cr.node.changefeed.lagging_ranges" ,
357+ labelMatchers : []string {"db=\" yours\" " , "status__=\" paused\" " },
358+ expectedSource : "7" ,
359+ expectedValue : 0 ,
360+ },
361+ {
362+ name : "histogram default -count" ,
363+ metricPrefix : "cr.node.changefeed.stage.downstream_client_send.latency" ,
364+ labelMatchers : []string {"scope=\" default\" " , "-count" },
365+ expectedSource : "7" ,
366+ expectedValue : 2 ,
367+ },
368+ {
369+ name : "histogram user -count" ,
370+ metricPrefix : "cr.node.changefeed.stage.downstream_client_send.latency" ,
371+ labelMatchers : []string {"scope=\" user\" " , "-count" },
372+ expectedSource : "7" ,
373+ expectedValue : 3 ,
374+ },
375+ {
376+ name : "histogram default -avg" ,
377+ metricPrefix : "cr.node.changefeed.stage.downstream_client_send.latency" ,
378+ labelMatchers : []string {"scope=\" default\" " , "-avg" },
379+ expectedSource : "7" ,
380+ expectedValue : 150 ,
381+ },
382+ {
383+ name : "histogram user -avg" ,
384+ metricPrefix : "cr.node.changefeed.stage.downstream_client_send.latency" ,
385+ labelMatchers : []string {"scope=\" user\" " , "-avg" },
386+ expectedSource : "7" ,
387+ expectedValue : 400 ,
388+ },
389+ }
365390
366- // Check for changefeed.stage.downstream_client_send.latency with scope labels
367- if strings .Contains (ts .Name , "cr.node.changefeed.stage.downstream_client_send.latency" ) {
368- if strings .Contains (ts .Name , "scope=\" default\" " ) && strings .Contains (ts .Name , "-count" ) {
369- foundHistogramDefaultCount = true
370- require .Equal (t , "7" , ts .Source , "Expected source to be node ID 7" )
371- require .Len (t , ts .Datapoints , 1 )
372- require .Equal (t , float64 (2 ), ts .Datapoints [0 ].Value )
373- }
374- if strings .Contains (ts .Name , "scope=\" user\" " ) && strings .Contains (ts .Name , "-count" ) {
375- foundHistogramUserCount = true
376- require .Equal (t , "7" , ts .Source , "Expected source to be node ID 7" )
377- require .Len (t , ts .Datapoints , 1 )
378- require .Equal (t , float64 (3 ), ts .Datapoints [0 ].Value )
391+ for _ , tc := range appMetricTestCases {
392+ var found bool
393+ for _ , ts := range childData {
394+ if ! strings .Contains (ts .Name , tc .metricPrefix ) {
395+ continue
379396 }
380- if strings .Contains (ts .Name , "scope=\" default\" " ) && strings .Contains (ts .Name , "-avg" ) {
381- foundHistogramDefaultAvg = true
382- require .Equal (t , "7" , ts .Source , "Expected source to be node ID 7" )
383- require .Len (t , ts .Datapoints , 1 )
384- require .Equal (t , float64 (150 ), ts .Datapoints [0 ].Value )
397+ allMatch := true
398+ for _ , matcher := range tc .labelMatchers {
399+ if ! strings .Contains (ts .Name , matcher ) {
400+ allMatch = false
401+ break
402+ }
385403 }
386- if strings .Contains (ts .Name , "scope=\" user\" " ) && strings .Contains (ts .Name , "-avg" ) {
387- foundHistogramUserAvg = true
388- require .Equal (t , "7" , ts .Source , "Expected source to be node ID 7" )
389- require .Len (t , ts .Datapoints , 1 )
390- require .Equal (t , float64 (400 ), ts .Datapoints [0 ].Value )
404+ if ! allMatch {
405+ continue
391406 }
407+ found = true
408+ require .Equal (t , tc .expectedSource , ts .Source , "Expected source for %s" , tc .name )
409+ require .Len (t , ts .Datapoints , 1 , "Expected 1 datapoint for %s" , tc .name )
410+ require .Equal (t , tc .expectedValue , ts .Datapoints [0 ].Value , "Expected value for %s" , tc .name )
411+ break
392412 }
413+ require .True (t , found , "Expected to find %s" , tc .name )
393414 }
394415
395- require .True (t , foundCounterFeedA123 , "Expected to find changefeed.emitted_messages with some_id=123 and feed_id=feed-a" )
396- require .True (t , foundCounterFeedB456 , "Expected to find changefeed.emitted_messages with some_id=456 and feed_id=feed-b" )
397- require .True (t , foundGaugeMineActive , "Expected to find changefeed.lagging_ranges with db=mine and status=active" )
398- require .True (t , foundGaugeYoursPaused , "Expected to find changefeed.lagging_ranges with db=yours and status=paused" )
399- require .True (t , foundHistogramDefaultCount , "Expected to find changefeed.stage.downstream_client_send.latency with scope=default" )
400- require .True (t , foundHistogramUserCount , "Expected to find changefeed.stage.downstream_client_send.latency with scope=user" )
401- require .True (t , foundHistogramDefaultAvg , "Expected to find changefeed.stage.downstream_client_send.latency with scope=default" )
402- require .True (t , foundHistogramUserAvg , "Expected to find changefeed.stage.downstream_client_send.latency with scope=user" )
403-
404416 // ========================================
405417 // Verify that tenant changefeed child metrics are collected with proper source
406418 // ========================================
@@ -441,48 +453,70 @@ func TestMetricsRecorderLabels(t *testing.T) {
441453 // Get time series data with child metrics enabled
442454 tenantChildData := recorder .GetTimeSeriesData (true )
443455
444- var foundTenantCounterFeed1 bool
445- var foundTenantCounterFeed2 bool
446- var foundTenantGaugeDefault bool
447- var foundTenantGaugeUser bool
448-
449- for _ , ts := range tenantChildData {
450- // Verify tenant changefeed metrics have correct source (7-123 for node 7, tenant 123)
451- if strings .Contains (ts .Name , "cr.node.changefeed.emitted_messages" ) {
452- if strings .Contains (ts .Name , `scope="default"` ) && strings .Contains (ts .Name , `feed_id="tenant-feed-1"` ) {
453- foundTenantCounterFeed1 = true
454- require .Equal (t , "7-123" , ts .Source , "Expected tenant source format node-tenant" )
455- require .Len (t , ts .Datapoints , 1 )
456- require .Equal (t , float64 (500 ), ts .Datapoints [0 ].Value )
457- }
458- if strings .Contains (ts .Name , `scope="user"` ) && strings .Contains (ts .Name , `feed_id="tenant-feed-2"` ) {
459- foundTenantCounterFeed2 = true
460- require .Equal (t , "7-123" , ts .Source , "Expected tenant source format node-tenant" )
461- require .Len (t , ts .Datapoints , 1 )
462- require .Equal (t , float64 (750 ), ts .Datapoints [0 ].Value )
463- }
464- }
456+ // Define test cases for tenant metrics
457+ tenantMetricTestCases := []struct {
458+ name string
459+ metricPrefix string
460+ labelMatchers []string
461+ expectedSource string
462+ expectedValue float64
463+ }{
464+ {
465+ name : "tenant counter default with tenant-feed-1" ,
466+ metricPrefix : "cr.node.changefeed.emitted_messages" ,
467+ labelMatchers : []string {`scope="default"` , `feed_id="tenant-feed-1"` },
468+ expectedSource : "7-123" ,
469+ expectedValue : 500 ,
470+ },
471+ {
472+ name : "tenant counter user with tenant-feed-2" ,
473+ metricPrefix : "cr.node.changefeed.emitted_messages" ,
474+ labelMatchers : []string {`scope="user"` , `feed_id="tenant-feed-2"` },
475+ expectedSource : "7-123" ,
476+ expectedValue : 750 ,
477+ },
478+ {
479+ name : "tenant gauge default" ,
480+ metricPrefix : "cr.node.changefeed.backfill_pending_ranges" ,
481+ labelMatchers : []string {`scope="default"` },
482+ expectedSource : "7-123" ,
483+ expectedValue : 2 ,
484+ },
485+ {
486+ name : "tenant gauge user" ,
487+ metricPrefix : "cr.node.changefeed.backfill_pending_ranges" ,
488+ labelMatchers : []string {`scope="user"` },
489+ expectedSource : "7-123" ,
490+ expectedValue : 1 ,
491+ },
492+ }
465493
466- if strings .Contains (ts .Name , "cr.node.changefeed.backfill_pending_ranges" ) {
467- if strings .Contains (ts .Name , `scope="default"` ) {
468- foundTenantGaugeDefault = true
469- require .Equal (t , "7-123" , ts .Source , "Expected tenant source format node-tenant" )
470- require .Len (t , ts .Datapoints , 1 )
471- require .Equal (t , float64 (2 ), ts .Datapoints [0 ].Value )
494+ // Verify tenant metrics
495+ for _ , tc := range tenantMetricTestCases {
496+ var found bool
497+ for _ , ts := range tenantChildData {
498+ if ! strings .Contains (ts .Name , tc .metricPrefix ) {
499+ continue
500+ }
501+ // Check if all label matchers are present
502+ allMatch := true
503+ for _ , matcher := range tc .labelMatchers {
504+ if ! strings .Contains (ts .Name , matcher ) {
505+ allMatch = false
506+ break
507+ }
472508 }
473- if strings .Contains (ts .Name , `scope="user"` ) {
474- foundTenantGaugeUser = true
475- require .Equal (t , "7-123" , ts .Source , "Expected tenant source format node-tenant" )
476- require .Len (t , ts .Datapoints , 1 )
477- require .Equal (t , float64 (1 ), ts .Datapoints [0 ].Value )
509+ if ! allMatch {
510+ continue
478511 }
512+ found = true
513+ require .Equal (t , tc .expectedSource , ts .Source , "Expected source for %s" , tc .name )
514+ require .Len (t , ts .Datapoints , 1 , "Expected 1 datapoint for %s" , tc .name )
515+ require .Equal (t , tc .expectedValue , ts .Datapoints [0 ].Value , "Expected value for %s" , tc .name )
516+ break
479517 }
518+ require .True (t , found , "Expected to find %s" , tc .name )
480519 }
481-
482- require .True (t , foundTenantCounterFeed1 , "Expected to find tenant changefeed.emitted_messages with scope=default and feed_id=tenant-feed-1" )
483- require .True (t , foundTenantCounterFeed2 , "Expected to find tenant changefeed.emitted_messages with scope=user and feed_id=tenant-feed-2" )
484- require .True (t , foundTenantGaugeDefault , "Expected to find tenant changefeed.backfill_pending_ranges with scope=default" )
485- require .True (t , foundTenantGaugeUser , "Expected to find tenant changefeed.backfill_pending_ranges with scope=user" )
486520}
487521
488522func TestRegistryRecorder_RecordChild (t * testing.T ) {
@@ -1250,67 +1284,33 @@ func TestRecordChangefeedChildMetrics(t *testing.T) {
12501284
12511285func BenchmarkRecordChangefeedChildMetrics (b * testing.B ) {
12521286 manual := timeutil .NewManualTime (timeutil .Unix (0 , 100 ))
1287+ enableChildCollection := true
12531288
1254- benchmarks := []struct {
1255- name string
1256- numMetrics int // number of aggmetrics to create
1257- childrenPerMetric int // number of children per aggmetric
1258- }{
1259- {"5metrics_100children" , 5 , 100 },
1260- {"10metrics_100children" , 10 , 100 },
1261- {"10metrics_1024children" , 10 , 1024 },
1289+ // Get metrics from the allowed list and convert to slice for indexing
1290+ allowedMetricsList := make ([]string , 0 , len (allowedChangefeedMetrics ))
1291+ for metricName := range allowedChangefeedMetrics {
1292+ allowedMetricsList = append (allowedMetricsList , metricName )
12621293 }
12631294
1264- for _ , bm := range benchmarks {
1265- b .Run (bm .name , func (b * testing.B ) {
1295+ // Benchmark with varying numbers of child metrics
1296+ for childCount := 10 ; childCount <= 1024 ; childCount *= 10 {
1297+ b .Run (fmt .Sprintf ("children-%d" , childCount ), func (b * testing.B ) {
12661298 reg := metric .NewRegistry ()
1267- enableChildCollection := true
12681299
1269- // Get metrics from the allowed list and convert to slice for indexing
1270- allowedMetricsList := make ([]string , 0 , len (allowedChangefeedMetrics ))
1271- for metricName := range allowedChangefeedMetrics {
1272- allowedMetricsList = append (allowedMetricsList , metricName )
1273- }
1300+ // Create a single gauge with varying numbers of children
1301+ gauge := aggmetric .NewGauge (
1302+ metric.Metadata {
1303+ Name : allowedMetricsList [0 ],
1304+ TsdbRecordLabeled : & enableChildCollection ,
1305+ Category : metric .Metadata_CHANGEFEEDS ,
1306+ },
1307+ "job_id" ,
1308+ )
1309+ reg .AddMetric (gauge )
12741310
1275- // Create mix of counters and gauges using random metrics from allowed list
1276- for i := 0 ; i < bm .numMetrics ; i ++ {
1277- metricName := allowedMetricsList [rand .Intn (len (allowedMetricsList ))]
1278-
1279- if i % 2 == 0 {
1280- counter := aggmetric .NewCounter (
1281- metric.Metadata {
1282- Name : metricName ,
1283- TsdbRecordLabeled : & enableChildCollection ,
1284- Category : metric .Metadata_CHANGEFEEDS ,
1285- },
1286- "job_id" , "feed_id" ,
1287- )
1288- reg .AddMetric (counter )
1289-
1290- for j := 0 ; j < bm .childrenPerMetric ; j ++ {
1291- jobID := strconv .Itoa (i * bm .childrenPerMetric + j )
1292- feedID := strconv .Itoa (j )
1293- child := counter .AddChild (jobID , feedID )
1294- child .Inc (int64 (rand .Intn (1000 )))
1295- }
1296- } else {
1297- gauge := aggmetric .NewGauge (
1298- metric.Metadata {
1299- Name : metricName ,
1300- TsdbRecordLabeled : & enableChildCollection ,
1301- Category : metric .Metadata_CHANGEFEEDS ,
1302- },
1303- "job_id" , "feed_id" ,
1304- )
1305- reg .AddMetric (gauge )
1306-
1307- for j := 0 ; j < bm .childrenPerMetric ; j ++ {
1308- jobID := strconv .Itoa (i * bm .childrenPerMetric + j )
1309- feedID := strconv .Itoa (j )
1310- child := gauge .AddChild (jobID , feedID )
1311- child .Update (int64 (rand .Intn (1000 )))
1312- }
1313- }
1311+ for i := 0 ; i < childCount ; i ++ {
1312+ child := gauge .AddChild (strconv .Itoa (i ))
1313+ child .Update (int64 (rand .Intn (1000 )))
13141314 }
13151315
13161316 recorder := registryRecorder {
0 commit comments