github.com/m3db/m3@v1.5.0/src/metrics/encoding/protobuf/reset_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 protobuf
    22  
    23  import (
    24  	"testing"
    25  	"time"
    26  
    27  	"github.com/stretchr/testify/require"
    28  
    29  	"github.com/m3db/m3/src/metrics/generated/proto/aggregationpb"
    30  	"github.com/m3db/m3/src/metrics/generated/proto/metricpb"
    31  	"github.com/m3db/m3/src/metrics/generated/proto/pipelinepb"
    32  	"github.com/m3db/m3/src/metrics/generated/proto/policypb"
    33  )
    34  
    35  var (
    36  	testCounterBeforeResetProto = metricpb.Counter{
    37  		Id:              []byte("testCounter"),
    38  		Value:           1234,
    39  		ClientTimeNanos: 10,
    40  	}
    41  	testCounterAfterResetProto = metricpb.Counter{
    42  		Id:    []byte{},
    43  		Value: 0,
    44  	}
    45  	testBatchTimerBeforeResetProto = metricpb.BatchTimer{
    46  		Id:              []byte("testBatchTimer"),
    47  		Values:          []float64{13.45, 98.23},
    48  		ClientTimeNanos: 10,
    49  	}
    50  	testBatchTimerAfterResetProto = metricpb.BatchTimer{
    51  		Id:     []byte{},
    52  		Values: []float64{},
    53  	}
    54  	testGaugeBeforeResetProto = metricpb.Gauge{
    55  		Id:              []byte("testGauge"),
    56  		Value:           3.48,
    57  		ClientTimeNanos: 10,
    58  	}
    59  	testGaugeAfterResetProto = metricpb.Gauge{
    60  		Id:    []byte{},
    61  		Value: 0.0,
    62  	}
    63  	testTimedMetricBeforeResetProto = metricpb.TimedMetric{
    64  		Type:      metricpb.MetricType_COUNTER,
    65  		Id:        []byte("testTimedMetric"),
    66  		TimeNanos: 1234,
    67  		Value:     1.23,
    68  	}
    69  	testForwardedMetricBeforeResetProto = metricpb.ForwardedMetric{
    70  		Type:      metricpb.MetricType_COUNTER,
    71  		Id:        []byte("testForwardedMetric"),
    72  		TimeNanos: 1234,
    73  		Values:    []float64{1.23, -4.56},
    74  		Version:   1,
    75  	}
    76  	testForwardedMetricAfterResetProto = metricpb.ForwardedMetric{
    77  		Type:      metricpb.MetricType_UNKNOWN,
    78  		Id:        []byte{},
    79  		TimeNanos: 0,
    80  		Values:    []float64{},
    81  	}
    82  	testMetadatasBeforeResetProto = metricpb.StagedMetadatas{
    83  		Metadatas: []metricpb.StagedMetadata{
    84  			{
    85  				CutoverNanos: 1234,
    86  				Metadata: metricpb.Metadata{
    87  					Pipelines: []metricpb.PipelineMetadata{
    88  						{
    89  							ResendEnabled: true,
    90  						},
    91  					},
    92  				},
    93  			},
    94  			{
    95  				CutoverNanos: 5678,
    96  			},
    97  		},
    98  	}
    99  	testMetadatasAfterResetProto = metricpb.StagedMetadatas{
   100  		Metadatas: []metricpb.StagedMetadata{},
   101  	}
   102  	testForwardMetadataBeforeResetProto = metricpb.ForwardMetadata{
   103  		ResendEnabled: true,
   104  		Pipeline: pipelinepb.AppliedPipeline{
   105  			Ops: []pipelinepb.AppliedPipelineOp{
   106  				{
   107  					Type: pipelinepb.AppliedPipelineOp_ROLLUP,
   108  					Rollup: pipelinepb.AppliedRollupOp{
   109  						Id: []byte("foo"),
   110  						AggregationId: aggregationpb.AggregationID{
   111  							Id: 12,
   112  						},
   113  					},
   114  				},
   115  			},
   116  		},
   117  		SourceId:          342,
   118  		NumForwardedTimes: 23,
   119  	}
   120  	testForwardMetadataAfterResetProto = metricpb.ForwardMetadata{
   121  		Pipeline: pipelinepb.AppliedPipeline{
   122  			Ops: []pipelinepb.AppliedPipelineOp{},
   123  		},
   124  		SourceId:          0,
   125  		NumForwardedTimes: 0,
   126  	}
   127  )
   128  
   129  func TestReuseMetricWithMetadatasProtoNilProto(t *testing.T) {
   130  	require.NotPanics(t, func() { ReuseMetricWithMetadatasProto(nil) })
   131  }
   132  
   133  func TestReuseAggregatedMetricProto(t *testing.T) {
   134  	input := &metricpb.AggregatedMetric{
   135  		Metric: metricpb.TimedMetricWithStoragePolicy{
   136  			TimedMetric: testTimedMetricBeforeResetProto,
   137  			StoragePolicy: policypb.StoragePolicy{
   138  				Resolution: policypb.Resolution{
   139  					WindowSize: 10 * time.Second.Nanoseconds(),
   140  					Precision:  time.Second.Nanoseconds(),
   141  				},
   142  				Retention: policypb.Retention{
   143  					Period: (6 * time.Hour).Nanoseconds(),
   144  				},
   145  			},
   146  		},
   147  		EncodeNanos: 1234,
   148  	}
   149  	ReuseAggregatedMetricProto(input)
   150  	require.Equal(t, metricpb.AggregatedMetric{
   151  		Metric: metricpb.TimedMetricWithStoragePolicy{
   152  			TimedMetric:   metricpb.TimedMetric{Id: []byte{}},
   153  			StoragePolicy: policypb.StoragePolicy{},
   154  		},
   155  		EncodeNanos: 0,
   156  	}, *input)
   157  	require.True(t, cap(input.Metric.TimedMetric.Id) > 0)
   158  }
   159  
   160  func TestReuseMetricWithMetadatasProtoOnlyCounter(t *testing.T) {
   161  	input := &metricpb.MetricWithMetadatas{
   162  		Type: metricpb.MetricWithMetadatas_COUNTER_WITH_METADATAS,
   163  		CounterWithMetadatas: &metricpb.CounterWithMetadatas{
   164  			Counter:   testCounterBeforeResetProto,
   165  			Metadatas: testMetadatasBeforeResetProto,
   166  		},
   167  	}
   168  	expected := &metricpb.MetricWithMetadatas{
   169  		Type: metricpb.MetricWithMetadatas_UNKNOWN,
   170  		CounterWithMetadatas: &metricpb.CounterWithMetadatas{
   171  			Counter:   testCounterAfterResetProto,
   172  			Metadatas: testMetadatasAfterResetProto,
   173  		},
   174  	}
   175  	ReuseMetricWithMetadatasProto(input)
   176  	require.Equal(t, expected, input)
   177  	require.True(t, cap(input.CounterWithMetadatas.Counter.Id) > 0)
   178  	require.True(t, cap(input.CounterWithMetadatas.Metadatas.Metadatas) > 0)
   179  }
   180  
   181  func TestReuseMetricForEncoding(t *testing.T) {
   182  	input := metricpb.MetricWithMetadatas{
   183  		Type: metricpb.MetricWithMetadatas_COUNTER_WITH_METADATAS,
   184  		CounterWithMetadatas: &metricpb.CounterWithMetadatas{
   185  			Counter: metricpb.Counter{
   186  				Id: []byte("testCounter"),
   187  			},
   188  			Metadatas: metricpb.StagedMetadatas{
   189  				Metadatas: []metricpb.StagedMetadata{
   190  					{
   191  						Metadata: metricpb.Metadata{
   192  							Pipelines: []metricpb.PipelineMetadata{
   193  								{
   194  									ResendEnabled: true,
   195  									StoragePolicies: []policypb.StoragePolicy{
   196  										{
   197  											Resolution: policypb.Resolution{
   198  												WindowSize: 1000,
   199  											},
   200  											Retention: policypb.Retention{
   201  												Period: 1000,
   202  											},
   203  										},
   204  									},
   205  									Pipeline: pipelinepb.AppliedPipeline{
   206  										Ops: []pipelinepb.AppliedPipelineOp{
   207  											{
   208  												Rollup: pipelinepb.AppliedRollupOp{
   209  													Id: []byte("foobar"),
   210  												},
   211  											},
   212  										},
   213  									},
   214  								},
   215  							},
   216  						},
   217  					},
   218  					{
   219  						CutoverNanos: 5678,
   220  					},
   221  				},
   222  			},
   223  		},
   224  	}
   225  	b, err := input.Marshal()
   226  	require.NoError(t, err)
   227  
   228  	var pb metricpb.MetricWithMetadatas
   229  	require.NoError(t, pb.Unmarshal(b))
   230  	require.Equal(t, input, pb)
   231  
   232  	// verify all slices are empty with a non-zero capacity.
   233  	ReuseMetricWithMetadatasProto(&pb)
   234  	metas := pb.CounterWithMetadatas.Metadatas.Metadatas
   235  	require.True(t, cap(metas) > 0)
   236  	require.Empty(t, metas)
   237  	metas = metas[0:1]
   238  	pipes := metas[0].Metadata.Pipelines
   239  	require.True(t, cap(pipes) > 0)
   240  	require.Empty(t, pipes)
   241  	pipes = pipes[0:1]
   242  	sps := pipes[0].StoragePolicies
   243  	require.Empty(t, sps)
   244  	require.True(t, cap(sps) > 0)
   245  	ops := pipes[0].Pipeline.Ops
   246  	require.Empty(t, ops)
   247  	require.True(t, cap(ops) > 0)
   248  	ops = ops[0:1]
   249  	id := ops[0].Rollup.Id
   250  	require.Empty(t, id)
   251  	require.True(t, cap(id) > 0)
   252  
   253  	// verify the proto can be properly reused for unmarshaling
   254  	require.NoError(t, pb.Unmarshal(b))
   255  	require.Equal(t, input, pb)
   256  }
   257  
   258  func TestReuseMetricWithMetadatasProtoOnlyBatchTimer(t *testing.T) {
   259  	input := &metricpb.MetricWithMetadatas{
   260  		Type: metricpb.MetricWithMetadatas_BATCH_TIMER_WITH_METADATAS,
   261  		BatchTimerWithMetadatas: &metricpb.BatchTimerWithMetadatas{
   262  			BatchTimer: testBatchTimerBeforeResetProto,
   263  			Metadatas:  testMetadatasBeforeResetProto,
   264  		},
   265  	}
   266  	expected := &metricpb.MetricWithMetadatas{
   267  		Type: metricpb.MetricWithMetadatas_UNKNOWN,
   268  		BatchTimerWithMetadatas: &metricpb.BatchTimerWithMetadatas{
   269  			BatchTimer: testBatchTimerAfterResetProto,
   270  			Metadatas:  testMetadatasAfterResetProto,
   271  		},
   272  	}
   273  	ReuseMetricWithMetadatasProto(input)
   274  	require.Equal(t, expected, input)
   275  	require.True(t, cap(input.BatchTimerWithMetadatas.BatchTimer.Id) > 0)
   276  	require.True(t, cap(input.BatchTimerWithMetadatas.Metadatas.Metadatas) > 0)
   277  }
   278  
   279  func TestReuseMetricWithMetadatasProtoOnlyGauge(t *testing.T) {
   280  	input := &metricpb.MetricWithMetadatas{
   281  		Type: metricpb.MetricWithMetadatas_GAUGE_WITH_METADATAS,
   282  		GaugeWithMetadatas: &metricpb.GaugeWithMetadatas{
   283  			Gauge:     testGaugeBeforeResetProto,
   284  			Metadatas: testMetadatasBeforeResetProto,
   285  		},
   286  	}
   287  	expected := &metricpb.MetricWithMetadatas{
   288  		Type: metricpb.MetricWithMetadatas_UNKNOWN,
   289  		GaugeWithMetadatas: &metricpb.GaugeWithMetadatas{
   290  			Gauge:     testGaugeAfterResetProto,
   291  			Metadatas: testMetadatasAfterResetProto,
   292  		},
   293  	}
   294  	ReuseMetricWithMetadatasProto(input)
   295  	require.Equal(t, expected, input)
   296  	require.True(t, cap(input.GaugeWithMetadatas.Gauge.Id) > 0)
   297  	require.True(t, cap(input.GaugeWithMetadatas.Metadatas.Metadatas) > 0)
   298  }
   299  
   300  func TestReuseMetricWithMetadatasProtoOnlyForwardedMetric(t *testing.T) {
   301  	input := &metricpb.MetricWithMetadatas{
   302  		Type: metricpb.MetricWithMetadatas_FORWARDED_METRIC_WITH_METADATA,
   303  		ForwardedMetricWithMetadata: &metricpb.ForwardedMetricWithMetadata{
   304  			Metric:   testForwardedMetricBeforeResetProto,
   305  			Metadata: testForwardMetadataBeforeResetProto,
   306  		},
   307  	}
   308  	expected := &metricpb.MetricWithMetadatas{
   309  		Type: metricpb.MetricWithMetadatas_UNKNOWN,
   310  		ForwardedMetricWithMetadata: &metricpb.ForwardedMetricWithMetadata{
   311  			Metric:   testForwardedMetricAfterResetProto,
   312  			Metadata: testForwardMetadataAfterResetProto,
   313  		},
   314  	}
   315  	ReuseMetricWithMetadatasProto(input)
   316  	require.Equal(t, expected, input)
   317  	require.True(t, cap(input.ForwardedMetricWithMetadata.Metric.Id) > 0)
   318  	require.True(t, cap(input.ForwardedMetricWithMetadata.Metric.Values) > 0)
   319  	require.True(t, cap(input.ForwardedMetricWithMetadata.Metadata.Pipeline.Ops) > 0)
   320  }
   321  
   322  func TestReuseMetricWithMetadatasProtoAll(t *testing.T) {
   323  	input := &metricpb.MetricWithMetadatas{
   324  		Type: metricpb.MetricWithMetadatas_GAUGE_WITH_METADATAS,
   325  		CounterWithMetadatas: &metricpb.CounterWithMetadatas{
   326  			Counter:   testCounterBeforeResetProto,
   327  			Metadatas: testMetadatasBeforeResetProto,
   328  		},
   329  		BatchTimerWithMetadatas: &metricpb.BatchTimerWithMetadatas{
   330  			BatchTimer: testBatchTimerBeforeResetProto,
   331  			Metadatas:  testMetadatasBeforeResetProto,
   332  		},
   333  		GaugeWithMetadatas: &metricpb.GaugeWithMetadatas{
   334  			Gauge:     testGaugeBeforeResetProto,
   335  			Metadatas: testMetadatasBeforeResetProto,
   336  		},
   337  		ForwardedMetricWithMetadata: &metricpb.ForwardedMetricWithMetadata{
   338  			Metric:   testForwardedMetricBeforeResetProto,
   339  			Metadata: testForwardMetadataBeforeResetProto,
   340  		},
   341  	}
   342  	expected := &metricpb.MetricWithMetadatas{
   343  		Type: metricpb.MetricWithMetadatas_UNKNOWN,
   344  		CounterWithMetadatas: &metricpb.CounterWithMetadatas{
   345  			Counter:   testCounterAfterResetProto,
   346  			Metadatas: testMetadatasAfterResetProto,
   347  		},
   348  		BatchTimerWithMetadatas: &metricpb.BatchTimerWithMetadatas{
   349  			BatchTimer: testBatchTimerAfterResetProto,
   350  			Metadatas:  testMetadatasAfterResetProto,
   351  		},
   352  		GaugeWithMetadatas: &metricpb.GaugeWithMetadatas{
   353  			Gauge:     testGaugeAfterResetProto,
   354  			Metadatas: testMetadatasAfterResetProto,
   355  		},
   356  		ForwardedMetricWithMetadata: &metricpb.ForwardedMetricWithMetadata{
   357  			Metric:   testForwardedMetricAfterResetProto,
   358  			Metadata: testForwardMetadataAfterResetProto,
   359  		},
   360  	}
   361  	ReuseMetricWithMetadatasProto(input)
   362  	require.Equal(t, expected, input)
   363  	require.True(t, cap(input.CounterWithMetadatas.Counter.Id) > 0)
   364  	require.True(t, cap(input.CounterWithMetadatas.Metadatas.Metadatas) > 0)
   365  	require.True(t, cap(input.BatchTimerWithMetadatas.BatchTimer.Id) > 0)
   366  	require.True(t, cap(input.BatchTimerWithMetadatas.Metadatas.Metadatas) > 0)
   367  	require.True(t, cap(input.GaugeWithMetadatas.Gauge.Id) > 0)
   368  	require.True(t, cap(input.GaugeWithMetadatas.Metadatas.Metadatas) > 0)
   369  	require.True(t, cap(input.ForwardedMetricWithMetadata.Metric.Id) > 0)
   370  	require.True(t, cap(input.ForwardedMetricWithMetadata.Metric.Values) > 0)
   371  	require.True(t, cap(input.ForwardedMetricWithMetadata.Metadata.Pipeline.Ops) > 0)
   372  }