github.com/m3db/m3@v1.5.0/src/cmd/services/m3aggregator/config/runtime_test.go (about) 1 // Copyright (c) 2017 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 config 22 23 import ( 24 "testing" 25 "time" 26 27 "github.com/m3db/m3/src/aggregator/aggregator" 28 "github.com/m3db/m3/src/aggregator/runtime" 29 "github.com/m3db/m3/src/cluster/client" 30 "github.com/m3db/m3/src/cluster/generated/proto/commonpb" 31 "github.com/m3db/m3/src/cluster/kv/mem" 32 "github.com/m3db/m3/src/cluster/placement" 33 xtest "github.com/m3db/m3/src/x/test" 34 35 "github.com/golang/mock/gomock" 36 "github.com/stretchr/testify/require" 37 yaml "gopkg.in/yaml.v2" 38 ) 39 40 func TestRuntimeOptionsConfigurationNewRuntimeOptionsManager(t *testing.T) { 41 ctrl := gomock.NewController(t) 42 defer ctrl.Finish() 43 44 config := ` 45 kvConfig: 46 zone: test 47 environment: production 48 writeValuesPerMetricLimitPerSecondKey: rate-limit-key 49 writeValuesPerMetricLimitPerSecond: 0 50 writeNewMetricLimitClusterPerSecondKey: new-metric-limit-key 51 writeNewMetricLimitClusterPerSecond: 0 52 writeNewMetricNoLimitWarmupDuration: 10m 53 ` 54 var cfg RuntimeOptionsConfiguration 55 require.NoError(t, yaml.Unmarshal([]byte(config), &cfg)) 56 require.Equal(t, "test", cfg.KVConfig.Zone) 57 require.Equal(t, "production", cfg.KVConfig.Environment) 58 require.Equal(t, "rate-limit-key", cfg.WriteValuesPerMetricLimitPerSecondKey) 59 require.Equal(t, int64(0), cfg.WriteValuesPerMetricLimitPerSecond) 60 require.Equal(t, "new-metric-limit-key", cfg.WriteNewMetricLimitClusterPerSecondKey) 61 require.Equal(t, int64(0), cfg.WriteNewMetricLimitClusterPerSecond) 62 require.Equal(t, 10*time.Minute, cfg.WriteNewMetricNoLimitWarmupDuration) 63 64 initialValueLimit := int64(100) 65 proto := &commonpb.Int64Proto{Value: initialValueLimit} 66 memStore := mem.NewStore() 67 _, err := memStore.Set("rate-limit-key", proto) 68 require.NoError(t, err) 69 70 initialNewMetricLimit := int64(32) 71 proto = &commonpb.Int64Proto{Value: initialNewMetricLimit} 72 _, err = memStore.Set("new-metric-limit-key", proto) 73 require.NoError(t, err) 74 75 runtimeOptsManager := cfg.NewRuntimeOptionsManager() 76 testShards := []uint32{0, 1, 2, 3} 77 testPlacement := placement.NewPlacement().SetReplicaFactor(2).SetShards(testShards) 78 testPlacementManager := aggregator.NewMockPlacementManager(ctrl) 79 testPlacementManager.EXPECT().Placement().Return(testPlacement, nil).AnyTimes() 80 81 mockClient := client.NewMockClient(ctrl) 82 mockClient.EXPECT().Store(gomock.Any()).Return(memStore, nil) 83 logger := xtest.NewLogger(t) 84 cfg.WatchRuntimeOptionChanges(mockClient, runtimeOptsManager, testPlacementManager, logger) 85 runtimeOpts := runtimeOptsManager.RuntimeOptions() 86 expectedOpts := runtime.NewOptions(). 87 SetWriteValuesPerMetricLimitPerSecond(initialValueLimit). 88 SetWriteNewMetricLimitPerShardPerSecond(4). 89 SetWriteNewMetricNoLimitWarmupDuration(10 * time.Minute) 90 require.Equal(t, expectedOpts, runtimeOpts) 91 92 // Set a new value limit. 93 newValueLimit := int64(1000) 94 proto.Value = newValueLimit 95 _, err = memStore.Set("rate-limit-key", proto) 96 require.NoError(t, err) 97 expectedOpts = runtime.NewOptions(). 98 SetWriteValuesPerMetricLimitPerSecond(1000). 99 SetWriteNewMetricLimitPerShardPerSecond(4). 100 SetWriteNewMetricNoLimitWarmupDuration(10 * time.Minute) 101 for { 102 runtimeOpts = runtimeOptsManager.RuntimeOptions() 103 if compareRuntimeOptions(expectedOpts, runtimeOpts) { 104 break 105 } 106 time.Sleep(10 * time.Millisecond) 107 } 108 109 // Revert value limit to initial limit. 110 newValueLimit = 100 111 proto.Value = newValueLimit 112 _, err = memStore.Set("rate-limit-key", proto) 113 require.NoError(t, err) 114 expectedOpts = runtime.NewOptions(). 115 SetWriteValuesPerMetricLimitPerSecond(100). 116 SetWriteNewMetricLimitPerShardPerSecond(4). 117 SetWriteNewMetricNoLimitWarmupDuration(10 * time.Minute) 118 for { 119 runtimeOpts = runtimeOptsManager.RuntimeOptions() 120 if compareRuntimeOptions(expectedOpts, runtimeOpts) { 121 break 122 } 123 time.Sleep(10 * time.Millisecond) 124 } 125 126 // Set a new new-metric limit. 127 newNewMetricLimit := int64(128) 128 proto.Value = newNewMetricLimit 129 _, err = memStore.Set("new-metric-limit-key", proto) 130 require.NoError(t, err) 131 expectedOpts = runtime.NewOptions(). 132 SetWriteValuesPerMetricLimitPerSecond(100). 133 SetWriteNewMetricLimitPerShardPerSecond(16). 134 SetWriteNewMetricNoLimitWarmupDuration(10 * time.Minute) 135 for { 136 runtimeOpts = runtimeOptsManager.RuntimeOptions() 137 if compareRuntimeOptions(expectedOpts, runtimeOpts) { 138 break 139 } 140 time.Sleep(10 * time.Millisecond) 141 } 142 143 // Revert to default new-metric limit. 144 newNewMetricLimit = int64(32) 145 proto.Value = newNewMetricLimit 146 _, err = memStore.Set("new-metric-limit-key", proto) 147 require.NoError(t, err) 148 expectedOpts = runtime.NewOptions(). 149 SetWriteValuesPerMetricLimitPerSecond(100). 150 SetWriteNewMetricLimitPerShardPerSecond(4). 151 SetWriteNewMetricNoLimitWarmupDuration(10 * time.Minute) 152 for { 153 runtimeOpts = runtimeOptsManager.RuntimeOptions() 154 if compareRuntimeOptions(expectedOpts, runtimeOpts) { 155 break 156 } 157 time.Sleep(10 * time.Millisecond) 158 } 159 } 160 161 func compareRuntimeOptions(expected, actual runtime.Options) bool { 162 return expected.WriteNewMetricLimitPerShardPerSecond() == actual.WriteNewMetricLimitPerShardPerSecond() && 163 expected.WriteNewMetricNoLimitWarmupDuration() == actual.WriteNewMetricNoLimitWarmupDuration() && 164 expected.WriteValuesPerMetricLimitPerSecond() == actual.WriteValuesPerMetricLimitPerSecond() 165 }