github.com/livekit/protocol@v1.39.3/utils/metrics_batch_builder_test.go (about) 1 // Copyright 2023 LiveKit, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package utils 16 17 import ( 18 "testing" 19 "time" 20 21 "github.com/stretchr/testify/require" 22 "google.golang.org/protobuf/proto" 23 "google.golang.org/protobuf/types/known/timestamppb" 24 25 "github.com/livekit/protocol/livekit" 26 "github.com/livekit/protocol/utils/mono" 27 ) 28 29 func TestMetricsBatchBuilder(t *testing.T) { 30 t.Run("basic", func(t *testing.T) { 31 at := mono.Now() 32 normalizedAt := mono.Now().Add(10 * time.Millisecond) 33 expected := &livekit.MetricsBatch{ 34 TimestampMs: at.UnixMilli(), 35 NormalizedTimestamp: timestamppb.New(normalizedAt), 36 } 37 38 mbb := NewMetricsBatchBuilder() 39 require.True(t, mbb.IsEmpty()) 40 mbb.SetTime( 41 time.Unix(0, expected.TimestampMs*int64(time.Millisecond)), 42 expected.NormalizedTimestamp.AsTime(), 43 ) 44 mb := mbb.ToProto() 45 require.True(t, proto.Equal(expected, mb)) 46 }) 47 48 t.Run("time series metric", func(t *testing.T) { 49 at := mono.Now() 50 normalizedAt := mono.Now().Add(10 * time.Millisecond) 51 52 expected := &livekit.MetricsBatch{ 53 TimestampMs: at.UnixMilli(), 54 NormalizedTimestamp: timestamppb.New(normalizedAt), 55 StrData: []string{ 56 "PA_1", 57 "TR_VC1", 58 "f", 59 "CustomMetric", 60 "TR_VC2", 61 "q", 62 "PA_2", 63 }, 64 TimeSeries: []*livekit.TimeSeriesMetric{ 65 { 66 Label: uint32(livekit.MetricLabel_PUBLISHER_RTT), 67 ParticipantIdentity: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE), 68 TrackSid: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 1, 69 Samples: []*livekit.MetricSample{ 70 { 71 TimestampMs: at.UnixMilli(), 72 NormalizedTimestamp: timestamppb.New(normalizedAt), 73 Value: 42.4, 74 }, 75 { 76 TimestampMs: at.UnixMilli(), 77 NormalizedTimestamp: timestamppb.New(normalizedAt), 78 Value: 52.4, 79 }, 80 { 81 TimestampMs: at.UnixMilli(), 82 NormalizedTimestamp: timestamppb.New(normalizedAt), 83 Value: 62.4, 84 }, 85 }, 86 Rid: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 2, 87 }, 88 { 89 Label: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 3, 90 ParticipantIdentity: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE), 91 TrackSid: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 4, 92 Samples: []*livekit.MetricSample{ 93 { 94 TimestampMs: at.UnixMilli(), 95 NormalizedTimestamp: timestamppb.New(normalizedAt), 96 Value: 72.4, 97 }, 98 { 99 TimestampMs: at.UnixMilli(), 100 NormalizedTimestamp: timestamppb.New(normalizedAt), 101 Value: 82.4, 102 }, 103 { 104 TimestampMs: at.UnixMilli(), 105 NormalizedTimestamp: timestamppb.New(normalizedAt), 106 Value: 92.4, 107 }, 108 }, 109 Rid: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 5, 110 }, 111 { 112 Label: uint32(livekit.MetricLabel_SUBSCRIBER_RTT), 113 ParticipantIdentity: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 6, 114 Samples: []*livekit.MetricSample{ 115 { 116 TimestampMs: at.UnixMilli(), 117 NormalizedTimestamp: timestamppb.New(normalizedAt), 118 Value: 102.4, 119 }, 120 }, 121 }, 122 { 123 Label: uint32(livekit.MetricLabel_CLIENT_VIDEO_SUBSCRIBER_FREEZE_COUNT), 124 ParticipantIdentity: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE), 125 Samples: []*livekit.MetricSample{ 126 { 127 TimestampMs: at.UnixMilli(), 128 NormalizedTimestamp: timestamppb.New(normalizedAt), 129 Value: 102.4, 130 }, 131 }, 132 }, 133 }, 134 } 135 136 mbb := NewMetricsBatchBuilder() 137 mbb.SetTime(at, normalizedAt) 138 mbb.SetRestrictedLabels(MetricRestrictedLabels{ 139 LabelRanges: []MetricLabelRange{ 140 { 141 StartInclusive: livekit.MetricLabel_CLIENT_VIDEO_SUBSCRIBER_FREEZE_COUNT, 142 EndInclusive: livekit.MetricLabel_CLIENT_VIDEO_PUBLISHER_QUALITY_LIMITATION_DURATION_OTHER, 143 }, 144 }, 145 ParticipantIdentity: "PA_1", 146 }) 147 148 // should not be able to add invalid metric label index 149 _, err := mbb.AddTimeSeriesMetric(TimeSeriesMetric{ 150 MetricLabel: livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE, 151 }) 152 require.ErrorIs(t, err, ErrInvalidMetricLabel) 153 154 // add a time series metric 155 ts1Idx, err := mbb.AddTimeSeriesMetric(TimeSeriesMetric{ 156 MetricLabel: livekit.MetricLabel_PUBLISHER_RTT, 157 ParticipantIdentity: "PA_1", 158 TrackID: "TR_VC1", 159 Samples: []MetricSample{ 160 { 161 At: at, 162 NormalizedAt: normalizedAt, 163 Value: 42.4, 164 }, 165 }, 166 Rid: "f", 167 }) 168 require.NoError(t, err) 169 require.False(t, mbb.IsEmpty()) 170 171 // should not be able to add sample to invalid index 172 err = mbb.AddMetricSamplesToTimeSeriesMetric(-1, nil) 173 require.ErrorIs(t, err, ErrInvalidTimeSeriesMetricIndex) 174 err = mbb.AddMetricSamplesToTimeSeriesMetric(ts1Idx+1, nil) 175 require.ErrorIs(t, err, ErrInvalidTimeSeriesMetricIndex) 176 177 // add a second one 178 ts2Idx, err := mbb.AddTimeSeriesMetric(TimeSeriesMetric{ 179 CustomMetricLabel: "CustomMetric", 180 ParticipantIdentity: "PA_1", 181 TrackID: "TR_VC2", 182 Samples: []MetricSample{ 183 { 184 At: at, 185 NormalizedAt: normalizedAt, 186 Value: 72.4, 187 }, 188 }, 189 Rid: "q", 190 }) 191 require.NoError(t, err) 192 193 // add extra samples to first metric to ensure it gets added to the right metric 194 err = mbb.AddMetricSamplesToTimeSeriesMetric(ts1Idx, []MetricSample{ 195 { 196 At: at, 197 NormalizedAt: normalizedAt, 198 Value: 52.4, 199 }, 200 { 201 At: at, 202 NormalizedAt: normalizedAt, 203 Value: 62.4, 204 }, 205 }) 206 require.NoError(t, err) 207 208 // add extra samples to second metric to ensure it gets added to the right metric 209 err = mbb.AddMetricSamplesToTimeSeriesMetric(ts2Idx, []MetricSample{ 210 { 211 At: at, 212 NormalizedAt: normalizedAt, 213 Value: 82.4, 214 }, 215 { 216 At: at, 217 NormalizedAt: normalizedAt, 218 Value: 92.4, 219 }, 220 }) 221 require.NoError(t, err) 222 223 // add a third metric with some fields not populated to ensure that those indices default to 0 224 _, err = mbb.AddTimeSeriesMetric(TimeSeriesMetric{ 225 MetricLabel: livekit.MetricLabel_SUBSCRIBER_RTT, 226 ParticipantIdentity: "PA_2", 227 Samples: []MetricSample{ 228 { 229 At: at, 230 NormalizedAt: normalizedAt, 231 Value: 102.4, 232 }, 233 }, 234 }) 235 require.NoError(t, err) 236 237 // should accept restricted labels from that participant 238 _, err = mbb.AddTimeSeriesMetric(TimeSeriesMetric{ 239 MetricLabel: livekit.MetricLabel_CLIENT_VIDEO_SUBSCRIBER_FREEZE_COUNT, 240 ParticipantIdentity: "PA_1", 241 Samples: []MetricSample{ 242 { 243 At: at, 244 NormalizedAt: normalizedAt, 245 Value: 102.4, 246 }, 247 }, 248 }) 249 require.NoError(t, err) 250 251 // should not accept restricted labels from any other participant 252 _, err = mbb.AddTimeSeriesMetric(TimeSeriesMetric{ 253 MetricLabel: livekit.MetricLabel_CLIENT_VIDEO_PUBLISHER_QUALITY_LIMITATION_DURATION_OTHER, 254 ParticipantIdentity: "PA_2", 255 Samples: []MetricSample{ 256 { 257 At: at, 258 NormalizedAt: normalizedAt, 259 Value: 102.4, 260 }, 261 }, 262 }) 263 require.ErrorIs(t, err, ErrFilteredMetricLabel) 264 265 mb := mbb.ToProto() 266 require.True(t, proto.Equal(expected, mb)) 267 }) 268 269 t.Run("event metric", func(t *testing.T) { 270 at := mono.Now() 271 atMilli := at.UnixMilli() 272 normalizedAt := mono.Now().Add(10 * time.Millisecond) 273 274 expected := &livekit.MetricsBatch{ 275 TimestampMs: at.UnixMilli(), 276 NormalizedTimestamp: timestamppb.New(normalizedAt), 277 StrData: []string{ 278 "PA_1", 279 "TR_VC1", 280 "f", 281 "CustomMetric", 282 "TR_VC2", 283 "PA_2", 284 }, 285 Events: []*livekit.EventMetric{ 286 { 287 Label: uint32(livekit.MetricLabel_PUBLISHER_RTT), 288 ParticipantIdentity: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE), 289 TrackSid: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 1, 290 StartTimestampMs: at.UnixMilli(), 291 EndTimestampMs: &atMilli, 292 NormalizedStartTimestamp: timestamppb.New(normalizedAt), 293 NormalizedEndTimestamp: timestamppb.New(normalizedAt), 294 Metadata: "md1", 295 Rid: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 2, 296 }, 297 { 298 Label: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 3, 299 ParticipantIdentity: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE), 300 TrackSid: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 4, 301 StartTimestampMs: at.UnixMilli(), 302 NormalizedStartTimestamp: timestamppb.New(normalizedAt), 303 Metadata: "md2", 304 }, 305 { 306 Label: uint32(livekit.MetricLabel_CLIENT_VIDEO_PUBLISHER_QUALITY_LIMITATION_DURATION_OTHER), 307 ParticipantIdentity: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE), 308 TrackSid: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 1, 309 StartTimestampMs: at.UnixMilli(), 310 EndTimestampMs: &atMilli, 311 NormalizedStartTimestamp: timestamppb.New(normalizedAt), 312 NormalizedEndTimestamp: timestamppb.New(normalizedAt), 313 Metadata: "md1", 314 Rid: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 2, 315 }, 316 }, 317 TimeSeries: []*livekit.TimeSeriesMetric{ 318 { 319 Label: uint32(livekit.MetricLabel_SUBSCRIBER_RTT), 320 ParticipantIdentity: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 5, 321 Samples: []*livekit.MetricSample{ 322 { 323 TimestampMs: at.UnixMilli(), 324 NormalizedTimestamp: timestamppb.New(normalizedAt), 325 Value: 102.4, 326 }, 327 }, 328 }, 329 }, 330 } 331 332 mbb := NewMetricsBatchBuilder() 333 mbb.SetTime(at, normalizedAt) 334 mbb.SetRestrictedLabels(MetricRestrictedLabels{ 335 LabelRanges: []MetricLabelRange{ 336 { 337 StartInclusive: livekit.MetricLabel_CLIENT_VIDEO_SUBSCRIBER_FREEZE_COUNT, 338 EndInclusive: livekit.MetricLabel_CLIENT_VIDEO_PUBLISHER_QUALITY_LIMITATION_DURATION_OTHER, 339 }, 340 }, 341 ParticipantIdentity: "PA_1", 342 }) 343 344 // should not be able to add invalid metric label index 345 err := mbb.AddEventMetric(EventMetric{ 346 MetricLabel: livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE, 347 }) 348 require.ErrorIs(t, err, ErrInvalidMetricLabel) 349 350 // add an event metric 351 err = mbb.AddEventMetric(EventMetric{ 352 MetricLabel: livekit.MetricLabel_PUBLISHER_RTT, 353 ParticipantIdentity: "PA_1", 354 TrackID: "TR_VC1", 355 StartedAt: at, 356 EndedAt: at, 357 NormalizedStartedAt: normalizedAt, 358 NormalizedEndedAt: normalizedAt, 359 Metadata: "md1", 360 Rid: "f", 361 }) 362 require.NoError(t, err) 363 364 // add a second one with some optional fields not included 365 err = mbb.AddEventMetric(EventMetric{ 366 CustomMetricLabel: "CustomMetric", 367 ParticipantIdentity: "PA_1", 368 TrackID: "TR_VC2", 369 StartedAt: at, 370 NormalizedStartedAt: normalizedAt, 371 Metadata: "md2", 372 }) 373 374 // should accept restricted label from PA_1 375 err = mbb.AddEventMetric(EventMetric{ 376 MetricLabel: livekit.MetricLabel_CLIENT_VIDEO_PUBLISHER_QUALITY_LIMITATION_DURATION_OTHER, 377 ParticipantIdentity: "PA_1", 378 TrackID: "TR_VC1", 379 StartedAt: at, 380 EndedAt: at, 381 NormalizedStartedAt: normalizedAt, 382 NormalizedEndedAt: normalizedAt, 383 Metadata: "md1", 384 Rid: "f", 385 }) 386 require.NoError(t, err) 387 388 // should not accept restricted label from !PA_1 389 err = mbb.AddEventMetric(EventMetric{ 390 MetricLabel: livekit.MetricLabel_CLIENT_VIDEO_PUBLISHER_QUALITY_LIMITATION_DURATION_OTHER, 391 ParticipantIdentity: "PA_2", 392 TrackID: "TR_VC1", 393 StartedAt: at, 394 EndedAt: at, 395 NormalizedStartedAt: normalizedAt, 396 NormalizedEndedAt: normalizedAt, 397 Metadata: "md1", 398 Rid: "f", 399 }) 400 require.ErrorIs(t, err, ErrFilteredMetricLabel) 401 402 // add a time series metric to ensure both time series metric and event metric can be in same batch 403 _, err = mbb.AddTimeSeriesMetric(TimeSeriesMetric{ 404 MetricLabel: livekit.MetricLabel_SUBSCRIBER_RTT, 405 ParticipantIdentity: "PA_2", 406 Samples: []MetricSample{ 407 { 408 At: at, 409 NormalizedAt: normalizedAt, 410 Value: 102.4, 411 }, 412 }, 413 }) 414 require.NoError(t, err) 415 416 mb := mbb.ToProto() 417 require.True(t, proto.Equal(expected, mb)) 418 }) 419 420 t.Run("merge", func(t *testing.T) { 421 at := mono.Now() 422 atMilli := at.UnixMilli() 423 normalizedAt := mono.Now().Add(10 * time.Millisecond) 424 425 expected := &livekit.MetricsBatch{ 426 TimestampMs: at.UnixMilli(), 427 NormalizedTimestamp: timestamppb.New(normalizedAt), 428 StrData: []string{ 429 "PA_1", 430 "TR_VC1", 431 "f", 432 "CustomMetric", 433 "TR_VC2", 434 "q", 435 "PA_2", 436 }, 437 Events: []*livekit.EventMetric{ 438 { 439 Label: uint32(livekit.MetricLabel_PUBLISHER_RTT), 440 ParticipantIdentity: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE), 441 TrackSid: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 1, 442 StartTimestampMs: at.UnixMilli(), 443 EndTimestampMs: &atMilli, 444 NormalizedStartTimestamp: timestamppb.New(normalizedAt), 445 NormalizedEndTimestamp: timestamppb.New(normalizedAt), 446 Metadata: "md1", 447 Rid: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 2, 448 }, 449 { 450 Label: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 3, 451 ParticipantIdentity: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE), 452 TrackSid: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 4, 453 StartTimestampMs: at.UnixMilli(), 454 NormalizedStartTimestamp: timestamppb.New(normalizedAt), 455 Metadata: "md2", 456 Rid: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 5, 457 }, 458 { 459 Label: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 3, 460 ParticipantIdentity: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE), 461 TrackSid: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 4, 462 StartTimestampMs: at.UnixMilli(), 463 NormalizedStartTimestamp: timestamppb.New(normalizedAt), 464 Metadata: "md2", 465 Rid: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 5, 466 }, 467 { 468 Label: uint32(livekit.MetricLabel_CLIENT_VIDEO_PUBLISHER_QUALITY_LIMITATION_DURATION_BANDWIDTH), 469 ParticipantIdentity: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE), 470 TrackSid: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 4, 471 StartTimestampMs: at.UnixMilli(), 472 NormalizedStartTimestamp: timestamppb.New(normalizedAt), 473 Metadata: "md2", 474 Rid: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 5, 475 }, 476 }, 477 TimeSeries: []*livekit.TimeSeriesMetric{ 478 { 479 Label: uint32(livekit.MetricLabel_SUBSCRIBER_RTT), 480 ParticipantIdentity: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 6, 481 Samples: []*livekit.MetricSample{ 482 { 483 TimestampMs: at.UnixMilli(), 484 NormalizedTimestamp: timestamppb.New(normalizedAt), 485 Value: 102.4, 486 }, 487 }, 488 }, 489 }, 490 } 491 492 mbb := NewMetricsBatchBuilder() 493 mbb.SetTime(at, normalizedAt) 494 mbb.SetRestrictedLabels(MetricRestrictedLabels{ 495 LabelRanges: []MetricLabelRange{ 496 { 497 StartInclusive: livekit.MetricLabel_CLIENT_VIDEO_SUBSCRIBER_FREEZE_COUNT, 498 EndInclusive: livekit.MetricLabel_CLIENT_VIDEO_PUBLISHER_QUALITY_LIMITATION_DURATION_OTHER, 499 }, 500 }, 501 ParticipantIdentity: "PA_1", 502 }) 503 504 // should not be able to add invalid metric label index 505 err := mbb.AddEventMetric(EventMetric{ 506 MetricLabel: livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE, 507 }) 508 require.ErrorIs(t, err, ErrInvalidMetricLabel) 509 510 // add an event metric 511 err = mbb.AddEventMetric(EventMetric{ 512 MetricLabel: livekit.MetricLabel_PUBLISHER_RTT, 513 ParticipantIdentity: "PA_1", 514 TrackID: "TR_VC1", 515 StartedAt: at, 516 EndedAt: at, 517 NormalizedStartedAt: normalizedAt, 518 NormalizedEndedAt: normalizedAt, 519 Metadata: "md1", 520 Rid: "f", 521 }) 522 require.NoError(t, err) 523 524 // add a second one with some optional fields not included 525 // including this here and in the one to merge to test index translation 526 err = mbb.AddEventMetric(EventMetric{ 527 CustomMetricLabel: "CustomMetric", 528 ParticipantIdentity: "PA_1", 529 TrackID: "TR_VC2", 530 StartedAt: at, 531 NormalizedStartedAt: normalizedAt, 532 Metadata: "md2", 533 Rid: "q", 534 }) 535 require.NoError(t, err) 536 537 toMerge := &livekit.MetricsBatch{ 538 TimestampMs: at.UnixMilli(), 539 NormalizedTimestamp: timestamppb.New(normalizedAt), 540 StrData: []string{ 541 "CustomMetric", 542 "PA_1", 543 "TR_VC2", 544 "q", 545 "PA_2", 546 }, 547 Events: []*livekit.EventMetric{ 548 { 549 Label: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE), 550 ParticipantIdentity: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 1, 551 TrackSid: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 2, 552 StartTimestampMs: at.UnixMilli(), 553 NormalizedStartTimestamp: timestamppb.New(normalizedAt), 554 Metadata: "md2", 555 Rid: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 3, 556 }, 557 { 558 Label: uint32(livekit.MetricLabel_CLIENT_VIDEO_PUBLISHER_QUALITY_LIMITATION_DURATION_BANDWIDTH), 559 ParticipantIdentity: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 1, 560 TrackSid: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 2, 561 StartTimestampMs: at.UnixMilli(), 562 NormalizedStartTimestamp: timestamppb.New(normalizedAt), 563 Metadata: "md2", 564 Rid: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 3, 565 }, 566 }, 567 TimeSeries: []*livekit.TimeSeriesMetric{ 568 { 569 Label: uint32(livekit.MetricLabel_SUBSCRIBER_RTT), 570 ParticipantIdentity: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 4, 571 Samples: []*livekit.MetricSample{ 572 { 573 TimestampMs: at.UnixMilli(), 574 NormalizedTimestamp: timestamppb.New(normalizedAt), 575 Value: 102.4, 576 }, 577 }, 578 }, 579 { 580 // should be filtered 581 Label: uint32(livekit.MetricLabel_CLIENT_VIDEO_PUBLISHER_QUALITY_LIMITATION_DURATION_CPU), 582 ParticipantIdentity: uint32(livekit.MetricLabel_METRIC_LABEL_PREDEFINED_MAX_VALUE) + 4, 583 Samples: []*livekit.MetricSample{ 584 { 585 TimestampMs: at.UnixMilli(), 586 NormalizedTimestamp: timestamppb.New(normalizedAt), 587 Value: 102.4, 588 }, 589 }, 590 }, 591 }, 592 } 593 mbb.Merge(toMerge) 594 595 mb := mbb.ToProto() 596 require.True(t, proto.Equal(expected, mb)) 597 }) 598 }