github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/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  }