github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/metrics/rules/rollup_target_test.go (about) 1 // Copyright (c) 2018 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package rules 22 23 import ( 24 "testing" 25 "time" 26 27 "github.com/m3db/m3/src/metrics/aggregation" 28 "github.com/m3db/m3/src/metrics/generated/proto/aggregationpb" 29 "github.com/m3db/m3/src/metrics/generated/proto/pipelinepb" 30 "github.com/m3db/m3/src/metrics/generated/proto/policypb" 31 "github.com/m3db/m3/src/metrics/generated/proto/rulepb" 32 "github.com/m3db/m3/src/metrics/generated/proto/transformationpb" 33 "github.com/m3db/m3/src/metrics/pipeline" 34 "github.com/m3db/m3/src/metrics/policy" 35 "github.com/m3db/m3/src/metrics/transformation" 36 xtime "github.com/m3db/m3/src/x/time" 37 38 "github.com/stretchr/testify/require" 39 ) 40 41 func TestNewRollupTargetV1ProtoNilProto(t *testing.T) { 42 _, err := newRollupTargetFromV1Proto(nil) 43 require.Equal(t, errNilRollupTargetV1Proto, err) 44 } 45 46 func TestNewRollupTargetV1ProtoInvalidProto(t *testing.T) { 47 proto := &rulepb.RollupTarget{ 48 Policies: []*policypb.Policy{ 49 &policypb.Policy{ 50 StoragePolicy: &policypb.StoragePolicy{ 51 Resolution: policypb.Resolution{ 52 WindowSize: 10 * time.Second.Nanoseconds(), 53 Precision: time.Second.Nanoseconds(), 54 }, 55 Retention: policypb.Retention{ 56 Period: 24 * time.Hour.Nanoseconds(), 57 }, 58 }, 59 AggregationTypes: []aggregationpb.AggregationType{10, 1234567}, 60 }, 61 }, 62 } 63 _, err := newRollupTargetFromV1Proto(proto) 64 require.Error(t, err) 65 } 66 67 func TestNewRollupTargetV1ProtoWithDefaultAggregationID(t *testing.T) { 68 proto := &rulepb.RollupTarget{ 69 Name: "testV1Proto", 70 Tags: []string{"testTag2", "testTag1"}, 71 Policies: []*policypb.Policy{ 72 { 73 StoragePolicy: &policypb.StoragePolicy{ 74 Resolution: policypb.Resolution{ 75 WindowSize: 10 * time.Second.Nanoseconds(), 76 Precision: time.Second.Nanoseconds(), 77 }, 78 Retention: policypb.Retention{ 79 Period: 24 * time.Hour.Nanoseconds(), 80 }, 81 }, 82 }, 83 { 84 StoragePolicy: &policypb.StoragePolicy{ 85 Resolution: policypb.Resolution{ 86 WindowSize: time.Minute.Nanoseconds(), 87 Precision: time.Minute.Nanoseconds(), 88 }, 89 Retention: policypb.Retention{ 90 Period: 720 * time.Hour.Nanoseconds(), 91 }, 92 }, 93 }, 94 { 95 StoragePolicy: &policypb.StoragePolicy{ 96 Resolution: policypb.Resolution{ 97 WindowSize: time.Hour.Nanoseconds(), 98 Precision: time.Hour.Nanoseconds(), 99 }, 100 Retention: policypb.Retention{ 101 Period: 365 * 24 * time.Hour.Nanoseconds(), 102 }, 103 }, 104 }, 105 }, 106 } 107 res, err := newRollupTargetFromV1Proto(proto) 108 require.NoError(t, err) 109 110 rr1, err := pipeline.NewRollupOp( 111 pipeline.GroupByRollupType, 112 "testV1Proto", 113 []string{"testTag1", "testTag2"}, 114 aggregation.DefaultID, 115 ) 116 require.NoError(t, err) 117 118 expected := rollupTarget{ 119 Pipeline: pipeline.NewPipeline([]pipeline.OpUnion{ 120 { 121 Type: pipeline.RollupOpType, 122 Rollup: rr1, 123 }, 124 }), 125 StoragePolicies: policy.StoragePolicies{ 126 policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour), 127 policy.NewStoragePolicy(time.Minute, xtime.Minute, 720*time.Hour), 128 policy.NewStoragePolicy(time.Hour, xtime.Hour, 365*24*time.Hour), 129 }, 130 } 131 require.Equal(t, expected, res) 132 } 133 134 func TestNewRollupTargetV1ProtoWithCustomAggregationID(t *testing.T) { 135 proto := &rulepb.RollupTarget{ 136 Name: "testV1Proto", 137 Tags: []string{"testTag2", "testTag1"}, 138 Policies: []*policypb.Policy{ 139 { 140 StoragePolicy: &policypb.StoragePolicy{ 141 Resolution: policypb.Resolution{ 142 WindowSize: 10 * time.Second.Nanoseconds(), 143 Precision: time.Second.Nanoseconds(), 144 }, 145 Retention: policypb.Retention{ 146 Period: 24 * time.Hour.Nanoseconds(), 147 }, 148 }, 149 AggregationTypes: []aggregationpb.AggregationType{1, 2}, 150 }, 151 { 152 StoragePolicy: &policypb.StoragePolicy{ 153 Resolution: policypb.Resolution{ 154 WindowSize: time.Minute.Nanoseconds(), 155 Precision: time.Minute.Nanoseconds(), 156 }, 157 Retention: policypb.Retention{ 158 Period: 720 * time.Hour.Nanoseconds(), 159 }, 160 }, 161 AggregationTypes: []aggregationpb.AggregationType{1, 2}, 162 }, 163 { 164 StoragePolicy: &policypb.StoragePolicy{ 165 Resolution: policypb.Resolution{ 166 WindowSize: time.Hour.Nanoseconds(), 167 Precision: time.Hour.Nanoseconds(), 168 }, 169 Retention: policypb.Retention{ 170 Period: 365 * 24 * time.Hour.Nanoseconds(), 171 }, 172 }, 173 AggregationTypes: []aggregationpb.AggregationType{1, 2}, 174 }, 175 }, 176 } 177 res, err := newRollupTargetFromV1Proto(proto) 178 require.NoError(t, err) 179 180 rr1, err := pipeline.NewRollupOp( 181 pipeline.GroupByRollupType, 182 "testV1Proto", 183 []string{"testTag1", "testTag2"}, 184 aggregation.MustCompressTypes(aggregation.Last, aggregation.Min), 185 ) 186 require.NoError(t, err) 187 188 expected := rollupTarget{ 189 Pipeline: pipeline.NewPipeline([]pipeline.OpUnion{ 190 { 191 Type: pipeline.RollupOpType, 192 Rollup: rr1, 193 }, 194 }), 195 StoragePolicies: policy.StoragePolicies{ 196 policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour), 197 policy.NewStoragePolicy(time.Minute, xtime.Minute, 720*time.Hour), 198 policy.NewStoragePolicy(time.Hour, xtime.Hour, 365*24*time.Hour), 199 }, 200 } 201 require.Equal(t, expected, res) 202 } 203 204 func TestNewRollupTargetV2ProtoNilProto(t *testing.T) { 205 _, err := newRollupTargetFromV2Proto(nil) 206 require.Equal(t, err, errNilRollupTargetV2Proto) 207 } 208 209 func TestNewRollupTargetV2ProtoInvalidPipelineProto(t *testing.T) { 210 proto := &rulepb.RollupTargetV2{ 211 Pipeline: &pipelinepb.Pipeline{ 212 Ops: []pipelinepb.PipelineOp{ 213 { 214 Type: pipelinepb.PipelineOp_TRANSFORMATION, 215 Transformation: &pipelinepb.TransformationOp{ 216 Type: transformationpb.TransformationType_UNKNOWN, 217 }, 218 }, 219 }, 220 }, 221 } 222 _, err := newRollupTargetFromV2Proto(proto) 223 require.Error(t, err) 224 } 225 226 func TestNewRollupTargetV2ProtoInvalidStoragePoliciesProto(t *testing.T) { 227 proto := &rulepb.RollupTargetV2{ 228 Pipeline: &pipelinepb.Pipeline{ 229 Ops: []pipelinepb.PipelineOp{ 230 { 231 Type: pipelinepb.PipelineOp_TRANSFORMATION, 232 Transformation: &pipelinepb.TransformationOp{ 233 Type: transformationpb.TransformationType_ABSOLUTE, 234 }, 235 }, 236 }, 237 }, 238 StoragePolicies: []*policypb.StoragePolicy{ 239 &policypb.StoragePolicy{ 240 Resolution: policypb.Resolution{Precision: 1234}, 241 Retention: policypb.Retention{Period: 5678}, 242 }, 243 }, 244 } 245 _, err := newRollupTargetFromV2Proto(proto) 246 require.Error(t, err) 247 } 248 249 func TestNewRollupTargetV2Proto(t *testing.T) { 250 proto := &rulepb.RollupTargetV2{ 251 Pipeline: &pipelinepb.Pipeline{ 252 Ops: []pipelinepb.PipelineOp{ 253 { 254 Type: pipelinepb.PipelineOp_AGGREGATION, 255 Aggregation: &pipelinepb.AggregationOp{ 256 Type: aggregationpb.AggregationType_SUM, 257 }, 258 }, 259 { 260 Type: pipelinepb.PipelineOp_TRANSFORMATION, 261 Transformation: &pipelinepb.TransformationOp{ 262 Type: transformationpb.TransformationType_ABSOLUTE, 263 }, 264 }, 265 { 266 Type: pipelinepb.PipelineOp_ROLLUP, 267 Rollup: &pipelinepb.RollupOp{ 268 NewName: "testRollupOp", 269 Tags: []string{"testTag2", "testTag1"}, 270 AggregationTypes: []aggregationpb.AggregationType{ 271 aggregationpb.AggregationType_MIN, 272 aggregationpb.AggregationType_MAX, 273 }, 274 }, 275 }, 276 }, 277 }, 278 StoragePolicies: []*policypb.StoragePolicy{ 279 { 280 Resolution: policypb.Resolution{ 281 WindowSize: 10 * time.Second.Nanoseconds(), 282 Precision: time.Second.Nanoseconds(), 283 }, 284 Retention: policypb.Retention{ 285 Period: 24 * time.Hour.Nanoseconds(), 286 }, 287 }, 288 { 289 Resolution: policypb.Resolution{ 290 WindowSize: time.Minute.Nanoseconds(), 291 Precision: time.Minute.Nanoseconds(), 292 }, 293 Retention: policypb.Retention{ 294 Period: 720 * time.Hour.Nanoseconds(), 295 }, 296 }, 297 { 298 Resolution: policypb.Resolution{ 299 WindowSize: time.Hour.Nanoseconds(), 300 Precision: time.Hour.Nanoseconds(), 301 }, 302 Retention: policypb.Retention{ 303 Period: 365 * 24 * time.Hour.Nanoseconds(), 304 }, 305 }, 306 }, 307 } 308 res, err := newRollupTargetFromV2Proto(proto) 309 require.NoError(t, err) 310 311 rr1, err := pipeline.NewRollupOp( 312 pipeline.GroupByRollupType, 313 "testRollupOp", 314 []string{"testTag1", "testTag2"}, 315 aggregation.MustCompressTypes(aggregation.Min, aggregation.Max), 316 ) 317 require.NoError(t, err) 318 319 expected := rollupTarget{ 320 Pipeline: pipeline.NewPipeline([]pipeline.OpUnion{ 321 { 322 Type: pipeline.AggregationOpType, 323 Aggregation: pipeline.AggregationOp{ 324 Type: aggregation.Sum, 325 }, 326 }, 327 { 328 Type: pipeline.TransformationOpType, 329 Transformation: pipeline.TransformationOp{ 330 Type: transformation.Absolute, 331 }, 332 }, 333 { 334 Type: pipeline.RollupOpType, 335 Rollup: rr1, 336 }, 337 }), 338 StoragePolicies: policy.StoragePolicies{ 339 policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour), 340 policy.NewStoragePolicy(time.Minute, xtime.Minute, 720*time.Hour), 341 policy.NewStoragePolicy(time.Hour, xtime.Hour, 365*24*time.Hour), 342 }, 343 } 344 require.Equal(t, expected, res) 345 } 346 347 func TestRollupTargetClone(t *testing.T) { 348 rr1, err := pipeline.NewRollupOp( 349 pipeline.GroupByRollupType, 350 "testRollupOp", 351 []string{"testTag1", "testTag2"}, 352 aggregation.MustCompressTypes(aggregation.Min, aggregation.Max), 353 ) 354 require.NoError(t, err) 355 356 source := rollupTarget{ 357 Pipeline: pipeline.NewPipeline([]pipeline.OpUnion{ 358 { 359 Type: pipeline.AggregationOpType, 360 Aggregation: pipeline.AggregationOp{ 361 Type: aggregation.Sum, 362 }, 363 }, 364 { 365 Type: pipeline.TransformationOpType, 366 Transformation: pipeline.TransformationOp{ 367 Type: transformation.Absolute, 368 }, 369 }, 370 { 371 Type: pipeline.RollupOpType, 372 Rollup: rr1, 373 }, 374 }), 375 StoragePolicies: policy.StoragePolicies{ 376 policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour), 377 policy.NewStoragePolicy(time.Minute, xtime.Minute, 720*time.Hour), 378 policy.NewStoragePolicy(time.Hour, xtime.Hour, 365*24*time.Hour), 379 }, 380 } 381 cloned := source.clone() 382 require.Equal(t, source, cloned) 383 384 // Assert that mutating the clone doesn't mutate the source. 385 cloned2 := source.clone() 386 cloned.StoragePolicies[0] = policy.NewStoragePolicy(time.Second, xtime.Second, 24*time.Hour) 387 require.Equal(t, cloned2, source) 388 } 389 390 func TestRollupTargetProtoInvalidPipeline(t *testing.T) { 391 target := rollupTarget{ 392 Pipeline: pipeline.NewPipeline([]pipeline.OpUnion{ 393 { 394 Type: pipeline.TransformationOpType, 395 Transformation: pipeline.TransformationOp{ 396 Type: transformation.UnknownType, 397 }, 398 }, 399 }), 400 StoragePolicies: policy.StoragePolicies{ 401 policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour), 402 policy.NewStoragePolicy(time.Minute, xtime.Minute, 720*time.Hour), 403 policy.NewStoragePolicy(time.Hour, xtime.Hour, 365*24*time.Hour), 404 }, 405 } 406 _, err := target.proto() 407 require.Error(t, err) 408 } 409 410 func TestRollupTargetProtoInvalidStoragePolicies(t *testing.T) { 411 target := rollupTarget{ 412 Pipeline: pipeline.NewPipeline([]pipeline.OpUnion{ 413 { 414 Type: pipeline.TransformationOpType, 415 Transformation: pipeline.TransformationOp{ 416 Type: transformation.Absolute, 417 }, 418 }, 419 }), 420 StoragePolicies: policy.StoragePolicies{ 421 policy.NewStoragePolicy(10*time.Second, xtime.Unit(100), 24*time.Hour), 422 }, 423 } 424 _, err := target.proto() 425 require.Error(t, err) 426 } 427 428 func TestRollupTargetProto(t *testing.T) { 429 rr1, err := pipeline.NewRollupOp( 430 pipeline.GroupByRollupType, 431 "testRollupOp", 432 []string{"testTag1", "testTag2"}, 433 aggregation.MustCompressTypes(aggregation.Min, aggregation.Max), 434 ) 435 require.NoError(t, err) 436 437 target := rollupTarget{ 438 Pipeline: pipeline.NewPipeline([]pipeline.OpUnion{ 439 { 440 Type: pipeline.AggregationOpType, 441 Aggregation: pipeline.AggregationOp{ 442 Type: aggregation.Sum, 443 }, 444 }, 445 { 446 Type: pipeline.TransformationOpType, 447 Transformation: pipeline.TransformationOp{ 448 Type: transformation.Absolute, 449 }, 450 }, 451 { 452 Type: pipeline.RollupOpType, 453 Rollup: rr1, 454 }, 455 }), 456 StoragePolicies: policy.StoragePolicies{ 457 policy.NewStoragePolicy(10*time.Second, xtime.Second, 24*time.Hour), 458 policy.NewStoragePolicy(time.Minute, xtime.Minute, 720*time.Hour), 459 policy.NewStoragePolicy(time.Hour, xtime.Hour, 365*24*time.Hour), 460 }, 461 } 462 res, err := target.proto() 463 require.NoError(t, err) 464 465 expected := &rulepb.RollupTargetV2{ 466 Pipeline: &pipelinepb.Pipeline{ 467 Ops: []pipelinepb.PipelineOp{ 468 { 469 Type: pipelinepb.PipelineOp_AGGREGATION, 470 Aggregation: &pipelinepb.AggregationOp{ 471 Type: aggregationpb.AggregationType_SUM, 472 }, 473 }, 474 { 475 Type: pipelinepb.PipelineOp_TRANSFORMATION, 476 Transformation: &pipelinepb.TransformationOp{ 477 Type: transformationpb.TransformationType_ABSOLUTE, 478 }, 479 }, 480 { 481 Type: pipelinepb.PipelineOp_ROLLUP, 482 Rollup: &pipelinepb.RollupOp{ 483 NewName: "testRollupOp", 484 Tags: []string{"testTag1", "testTag2"}, 485 AggregationTypes: []aggregationpb.AggregationType{ 486 aggregationpb.AggregationType_MIN, 487 aggregationpb.AggregationType_MAX, 488 }, 489 }, 490 }, 491 }, 492 }, 493 StoragePolicies: []*policypb.StoragePolicy{ 494 { 495 Resolution: policypb.Resolution{ 496 WindowSize: 10 * time.Second.Nanoseconds(), 497 Precision: time.Second.Nanoseconds(), 498 }, 499 Retention: policypb.Retention{ 500 Period: 24 * time.Hour.Nanoseconds(), 501 }, 502 }, 503 { 504 Resolution: policypb.Resolution{ 505 WindowSize: time.Minute.Nanoseconds(), 506 Precision: time.Minute.Nanoseconds(), 507 }, 508 Retention: policypb.Retention{ 509 Period: 720 * time.Hour.Nanoseconds(), 510 }, 511 }, 512 { 513 Resolution: policypb.Resolution{ 514 WindowSize: time.Hour.Nanoseconds(), 515 Precision: time.Hour.Nanoseconds(), 516 }, 517 Retention: policypb.Retention{ 518 Period: 365 * 24 * time.Hour.Nanoseconds(), 519 }, 520 }, 521 }, 522 } 523 require.Equal(t, expected, res) 524 }