github.com/m3db/m3@v1.5.0/src/aggregator/client/options.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 client 22 23 import ( 24 "errors" 25 "fmt" 26 "time" 27 28 "github.com/m3db/m3/src/aggregator/sharding" 29 "github.com/m3db/m3/src/cluster/placement" 30 "github.com/m3db/m3/src/metrics/encoding/protobuf" 31 "github.com/m3db/m3/src/x/clock" 32 "github.com/m3db/m3/src/x/instrument" 33 xio "github.com/m3db/m3/src/x/io" 34 ) 35 36 // AggregatorClientType determines the aggregator client type. 37 type AggregatorClientType int 38 39 const ( 40 // LegacyAggregatorClient is an alias for TCPAggregatorClient 41 LegacyAggregatorClient AggregatorClientType = iota 42 // M3MsgAggregatorClient is the M3Msg aggregator client type that uses M3Msg to 43 // handle publishing to a M3Msg topic the aggregator consumes from. 44 M3MsgAggregatorClient 45 // TCPAggregatorClient is the TCP aggregator client type and uses it's own 46 // TCP negotiation, load balancing and data transmission protocol. 47 TCPAggregatorClient 48 49 defaultAggregatorClient = LegacyAggregatorClient 50 51 defaultFlushWorkerCount = 64 52 53 // defaultMaxTimerBatchSize is the default maximum timer batch size. 54 // By default there is no limit on the timer batch size. 55 defaultMaxTimerBatchSize = 0 56 57 // defaultInstanceQueueSize determines how many protobuf payloads can be buffered 58 // before it must wait for an existing batch to be flushed to an instance. 59 defaultInstanceQueueSize = 128 60 61 // By default traffic is cut over to shards 10 minutes before the designated 62 // cutover time in case there are issues with the instances owning the shards. 63 defaultShardCutoverWarmupDuration = 10 * time.Minute 64 65 // By default traffic doesn't stop until one hour after the designated cutoff 66 // time in case there are issues with the instances taking over the shards 67 // and as such we need to switch the traffic back to the previous owner of the shards. 68 defaultShardCutoffLingerDuration = time.Hour 69 70 // By default the oldest metrics in the queue are dropped when it is full. 71 defaultDropType = DropOldest 72 73 // By default set maximum batch size to 8mb. 74 defaultMaxBatchSize = 2 << 22 75 ) 76 77 var ( 78 validAggregatorClientTypes = []AggregatorClientType{ 79 LegacyAggregatorClient, 80 M3MsgAggregatorClient, 81 TCPAggregatorClient, 82 } 83 84 errTCPClientNoWatcherOptions = errors.New("legacy client: no watcher options set") 85 errM3MsgClientNoOptions = errors.New("m3msg aggregator client: no m3msg options set") 86 errNoRWOpts = errors.New("no rw opts set for aggregator") 87 ) 88 89 func (t AggregatorClientType) String() string { 90 switch t { 91 case LegacyAggregatorClient: 92 return "legacy" 93 case M3MsgAggregatorClient: 94 return "m3msg" 95 case TCPAggregatorClient: 96 return "tcp" 97 } 98 return "unknown" 99 } 100 101 // MarshalYAML returns the YAML representation of the AggregatorClientType. 102 func (t AggregatorClientType) MarshalYAML() (interface{}, error) { 103 return t.String(), nil 104 } 105 106 // UnmarshalYAML unmarshals a AggregatorClientType into a valid type from string. 107 func (t *AggregatorClientType) UnmarshalYAML(unmarshal func(interface{}) error) error { 108 var str string 109 if err := unmarshal(&str); err != nil { 110 return err 111 } 112 if str == "" { 113 *t = defaultAggregatorClient 114 return nil 115 } 116 for _, valid := range validAggregatorClientTypes { 117 if str == valid.String() { 118 *t = valid 119 return nil 120 } 121 } 122 return fmt.Errorf("invalid AggregatorClientType: value=%s, valid=%v", 123 str, validAggregatorClientTypes) 124 } 125 126 // Options provide a set of client options. 127 type Options interface { 128 // Validate validates the client options. 129 Validate() error 130 131 // SetAggregatorClientType sets the client type. 132 SetAggregatorClientType(value AggregatorClientType) Options 133 134 // AggregatorClientType returns the client type. 135 AggregatorClientType() AggregatorClientType 136 137 // SetM3MsgOptions sets the M3Msg aggregator client options. 138 SetM3MsgOptions(value M3MsgOptions) Options 139 140 // M3MsgOptions returns the M3Msg aggregator client options. 141 M3MsgOptions() M3MsgOptions 142 143 // SetClockOptions sets the clock options. 144 SetClockOptions(value clock.Options) Options 145 146 // ClockOptions returns the clock options. 147 ClockOptions() clock.Options 148 149 // SetInstrumentOptions sets the instrument options. 150 SetInstrumentOptions(value instrument.Options) Options 151 152 // InstrumentOptions returns the instrument options. 153 InstrumentOptions() instrument.Options 154 155 // SetEncoderOptions sets the encoder options. 156 SetEncoderOptions(value protobuf.UnaggregatedOptions) Options 157 158 // EncoderOptions returns the encoder options. 159 EncoderOptions() protobuf.UnaggregatedOptions 160 161 // SetShardFn sets the sharding function. 162 SetShardFn(value sharding.ShardFn) Options 163 164 // ShardFn returns the sharding function. 165 ShardFn() sharding.ShardFn 166 167 // SetWatcherOptions sets the placement watcher options. 168 SetWatcherOptions(value placement.WatcherOptions) Options 169 170 // WatcherOptions returns the placement watcher options. 171 WatcherOptions() placement.WatcherOptions 172 173 // SetShardCutoverWarmupDuration sets the warm up duration for traffic cut over to a shard. 174 SetShardCutoverWarmupDuration(value time.Duration) Options 175 176 // ShardCutoverWarmupDuration returns the warm up duration for traffic cut over to a shard. 177 ShardCutoverWarmupDuration() time.Duration 178 179 // SetShardCutoffLingerDuration sets the linger duration for traffic cut off from a shard. 180 SetShardCutoffLingerDuration(value time.Duration) Options 181 182 // ShardCutoffLingerDuration returns the linger duration for traffic cut off from a shard. 183 ShardCutoffLingerDuration() time.Duration 184 185 // SetConnectionOptions sets the connection options. 186 SetConnectionOptions(value ConnectionOptions) Options 187 188 // ConnectionOptions returns the connection options. 189 ConnectionOptions() ConnectionOptions 190 191 // SetFlushWorkerCount sets the max number of workers used for flushing. 192 SetFlushWorkerCount(value int) Options 193 194 // FlushWorkerCount returns the max number of workers used for flushing. 195 FlushWorkerCount() int 196 197 // SetForceFlushEvery sets the duration between forced flushes. 198 SetForceFlushEvery(value time.Duration) Options 199 200 // ForceFlushEvery returns the duration, if any, between forced flushes. 201 ForceFlushEvery() time.Duration 202 203 // SetMaxTimerBatchSize sets the maximum timer batch size. 204 SetMaxTimerBatchSize(value int) Options 205 206 // MaxTimerBatchSize returns the maximum timer batch size. 207 MaxTimerBatchSize() int 208 209 // SetInstanceQueueSize sets the instance queue size. 210 SetInstanceQueueSize(value int) Options 211 212 // InstanceQueueSize returns the instance queue size. 213 InstanceQueueSize() int 214 215 // SetQueueDropType sets the strategy for which metrics should metrics should be dropped when 216 // the queue is full. 217 SetQueueDropType(value DropType) Options 218 219 // QueueDropType returns sets the strategy for which metrics should metrics should be dropped 220 // when the queue is full. 221 QueueDropType() DropType 222 223 // SetMaxBatchSize sets the buffer limit that triggers a write of queued buffers. 224 SetMaxBatchSize(value int) Options 225 226 // MaxBatchSize returns the maximum buffer size that triggers a queue drain. 227 MaxBatchSize() int 228 229 // SetRWOptions sets RW options. 230 SetRWOptions(value xio.Options) Options 231 232 // RWOptions returns the RW options. 233 RWOptions() xio.Options 234 } 235 236 type options struct { 237 watcherOpts placement.WatcherOptions 238 clockOpts clock.Options 239 instrumentOpts instrument.Options 240 encoderOpts protobuf.UnaggregatedOptions 241 m3msgOptions M3MsgOptions 242 connOpts ConnectionOptions 243 rwOpts xio.Options 244 shardFn sharding.ShardFn 245 shardCutoffLingerDuration time.Duration 246 shardCutoverWarmupDuration time.Duration 247 forceFlushEvery time.Duration 248 maxTimerBatchSize int 249 instanceQueueSize int 250 dropType DropType 251 maxBatchSize int 252 flushWorkerCount int 253 aggregatorClientType AggregatorClientType 254 } 255 256 // NewOptions creates a new set of client options. 257 func NewOptions() Options { 258 return &options{ 259 clockOpts: clock.NewOptions(), 260 instrumentOpts: instrument.NewOptions(), 261 encoderOpts: protobuf.NewUnaggregatedOptions(), 262 shardFn: sharding.DefaultHash.MustShardFn(), 263 shardCutoverWarmupDuration: defaultShardCutoverWarmupDuration, 264 shardCutoffLingerDuration: defaultShardCutoffLingerDuration, 265 watcherOpts: placement.NewWatcherOptions(), 266 connOpts: NewConnectionOptions(), 267 flushWorkerCount: defaultFlushWorkerCount, 268 maxTimerBatchSize: defaultMaxTimerBatchSize, 269 instanceQueueSize: defaultInstanceQueueSize, 270 dropType: defaultDropType, 271 maxBatchSize: defaultMaxBatchSize, 272 rwOpts: xio.NewOptions(), 273 } 274 } 275 276 func (o *options) Validate() error { 277 if o.rwOpts == nil { 278 return errNoRWOpts 279 } 280 switch o.aggregatorClientType { 281 case M3MsgAggregatorClient: 282 opts := o.m3msgOptions 283 if opts == nil { 284 return errM3MsgClientNoOptions 285 } 286 return opts.Validate() 287 case LegacyAggregatorClient: 288 fallthrough // intentional, LegacyAggregatorClient is an alias 289 case TCPAggregatorClient: 290 if o.watcherOpts == nil { 291 return errTCPClientNoWatcherOptions 292 } 293 return nil 294 default: 295 return fmt.Errorf("unknown client type: %v", o.aggregatorClientType) 296 } 297 } 298 299 func (o *options) SetAggregatorClientType(value AggregatorClientType) Options { 300 opts := *o 301 opts.aggregatorClientType = value 302 return &opts 303 } 304 305 func (o *options) AggregatorClientType() AggregatorClientType { 306 return o.aggregatorClientType 307 } 308 309 func (o *options) SetM3MsgOptions(value M3MsgOptions) Options { 310 opts := *o 311 opts.m3msgOptions = value 312 return &opts 313 } 314 315 func (o *options) M3MsgOptions() M3MsgOptions { 316 return o.m3msgOptions 317 } 318 319 func (o *options) SetClockOptions(value clock.Options) Options { 320 opts := *o 321 opts.clockOpts = value 322 return &opts 323 } 324 325 func (o *options) ClockOptions() clock.Options { 326 return o.clockOpts 327 } 328 329 func (o *options) SetInstrumentOptions(value instrument.Options) Options { 330 opts := *o 331 opts.instrumentOpts = value 332 return &opts 333 } 334 335 func (o *options) InstrumentOptions() instrument.Options { 336 return o.instrumentOpts 337 } 338 339 func (o *options) SetEncoderOptions(value protobuf.UnaggregatedOptions) Options { 340 opts := *o 341 opts.encoderOpts = value 342 return &opts 343 } 344 345 func (o *options) EncoderOptions() protobuf.UnaggregatedOptions { 346 return o.encoderOpts 347 } 348 349 func (o *options) SetShardFn(value sharding.ShardFn) Options { 350 opts := *o 351 opts.shardFn = value 352 return &opts 353 } 354 355 func (o *options) ShardFn() sharding.ShardFn { 356 return o.shardFn 357 } 358 359 func (o *options) SetShardCutoverWarmupDuration(value time.Duration) Options { 360 opts := *o 361 opts.shardCutoverWarmupDuration = value 362 return &opts 363 } 364 365 func (o *options) ShardCutoverWarmupDuration() time.Duration { 366 return o.shardCutoverWarmupDuration 367 } 368 369 func (o *options) SetShardCutoffLingerDuration(value time.Duration) Options { 370 opts := *o 371 opts.shardCutoffLingerDuration = value 372 return &opts 373 } 374 375 func (o *options) ShardCutoffLingerDuration() time.Duration { 376 return o.shardCutoffLingerDuration 377 } 378 379 func (o *options) SetWatcherOptions(value placement.WatcherOptions) Options { 380 opts := *o 381 opts.watcherOpts = value 382 return &opts 383 } 384 385 func (o *options) WatcherOptions() placement.WatcherOptions { 386 return o.watcherOpts 387 } 388 389 func (o *options) SetConnectionOptions(value ConnectionOptions) Options { 390 opts := *o 391 opts.connOpts = value 392 return &opts 393 } 394 395 func (o *options) ConnectionOptions() ConnectionOptions { 396 return o.connOpts 397 } 398 399 func (o *options) SetFlushWorkerCount(value int) Options { 400 opts := *o 401 opts.flushWorkerCount = value 402 return &opts 403 } 404 405 func (o *options) FlushWorkerCount() int { 406 return o.flushWorkerCount 407 } 408 409 func (o *options) SetForceFlushEvery(value time.Duration) Options { 410 opts := *o 411 opts.forceFlushEvery = value 412 return &opts 413 } 414 415 func (o *options) ForceFlushEvery() time.Duration { 416 return o.forceFlushEvery 417 } 418 419 func (o *options) SetMaxTimerBatchSize(value int) Options { 420 opts := *o 421 opts.maxTimerBatchSize = value 422 return &opts 423 } 424 425 func (o *options) MaxTimerBatchSize() int { 426 return o.maxTimerBatchSize 427 } 428 429 func (o *options) SetInstanceQueueSize(value int) Options { 430 opts := *o 431 opts.instanceQueueSize = value 432 return &opts 433 } 434 435 func (o *options) InstanceQueueSize() int { 436 return o.instanceQueueSize 437 } 438 439 func (o *options) SetQueueDropType(value DropType) Options { 440 opts := *o 441 opts.dropType = value 442 return &opts 443 } 444 445 func (o *options) QueueDropType() DropType { 446 return o.dropType 447 } 448 449 func (o *options) SetMaxBatchSize(value int) Options { 450 opts := *o 451 if value < 0 { 452 value = defaultMaxBatchSize 453 } 454 opts.maxBatchSize = value 455 456 return &opts 457 } 458 459 func (o *options) MaxBatchSize() int { 460 return o.maxBatchSize 461 } 462 463 func (o *options) SetRWOptions(value xio.Options) Options { 464 opts := *o 465 opts.rwOpts = value 466 return &opts 467 } 468 469 func (o *options) RWOptions() xio.Options { 470 return o.rwOpts 471 }