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  }