github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/query/storage/restrict_query_options.go (about)

     1  // Copyright (c) 2019 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 storage
    22  
    23  import (
    24  	"bytes"
    25  	"fmt"
    26  
    27  	"github.com/m3db/m3/src/metrics/policy"
    28  	"github.com/m3db/m3/src/query/models"
    29  	"github.com/m3db/m3/src/query/storage/m3/storagemetadata"
    30  )
    31  
    32  // Validate will validate the restrict fetch options.
    33  func (o *RestrictQueryOptions) Validate() error {
    34  	if o.RestrictByType != nil {
    35  		return o.RestrictByType.Validate()
    36  	}
    37  	for _, r := range o.RestrictByTypes {
    38  		if err := r.Validate(); err != nil {
    39  			return err
    40  		}
    41  	}
    42  	return nil
    43  }
    44  
    45  // GetRestrictByType provides the type restrictions if present; nil otherwise.
    46  func (o *RestrictQueryOptions) GetRestrictByType() *RestrictByType {
    47  	if o == nil {
    48  		return nil
    49  	}
    50  
    51  	return o.RestrictByType
    52  }
    53  
    54  // GetRestrictByTypes provides the types restrictions if present; nil otherwise.
    55  func (o *RestrictQueryOptions) GetRestrictByTypes() []*RestrictByType {
    56  	if o == nil {
    57  		return nil
    58  	}
    59  
    60  	return o.RestrictByTypes
    61  }
    62  
    63  // GetRestrictByTag provides the tag restrictions if present; nil otherwise.
    64  func (o *RestrictQueryOptions) GetRestrictByTag() *RestrictByTag {
    65  	if o == nil {
    66  		return nil
    67  	}
    68  
    69  	return o.RestrictByTag
    70  }
    71  
    72  // GetMatchers provides the tag matchers by which results are restricted if
    73  // present; nil otherwise.
    74  func (o *RestrictByTag) GetMatchers() models.Matchers {
    75  	if o == nil {
    76  		return nil
    77  	}
    78  
    79  	return o.Restrict
    80  }
    81  
    82  // Validate will validate the restrict type restrictions.
    83  func (o *RestrictByType) Validate() error {
    84  	switch o.MetricsType {
    85  	case storagemetadata.UnaggregatedMetricsType:
    86  		if o.StoragePolicy != policy.EmptyStoragePolicy {
    87  			return fmt.Errorf(
    88  				"expected no storage policy for unaggregated metrics type, "+
    89  					"instead got: %v", o.StoragePolicy.String())
    90  		}
    91  	case storagemetadata.AggregatedMetricsType:
    92  		if v := o.StoragePolicy.Resolution().Window; v <= 0 {
    93  			return fmt.Errorf(
    94  				"expected positive resolution window, instead got: %v", v)
    95  		}
    96  		if v := o.StoragePolicy.Resolution().Precision; v <= 0 {
    97  			return fmt.Errorf(
    98  				"expected positive resolution precision, instead got: %v", v)
    99  		}
   100  		if v := o.StoragePolicy.Retention().Duration(); v <= 0 {
   101  			return fmt.Errorf(
   102  				"expected positive retention, instead got: %v", v)
   103  		}
   104  	default:
   105  		return fmt.Errorf(
   106  			"unknown metrics type: %v", o.MetricsType)
   107  	}
   108  	return nil
   109  }
   110  
   111  // GetFilterByNames returns the tag names to filter out of the response.
   112  func (o *RestrictByTag) GetFilterByNames() [][]byte {
   113  	if o == nil {
   114  		return nil
   115  	}
   116  
   117  	if o.Strip != nil {
   118  		return o.Strip
   119  	}
   120  
   121  	o.Strip = make([][]byte, 0, len(o.Restrict))
   122  	for _, r := range o.Restrict {
   123  		o.Strip = append(o.Strip, r.Name)
   124  	}
   125  
   126  	return o.Strip
   127  }
   128  
   129  // WithAppliedOptions returns a copy of the fetch query applied options
   130  // that restricts the fetch with respect to labels that must be applied.
   131  func (q *FetchQuery) WithAppliedOptions(
   132  	opts *FetchOptions,
   133  ) *FetchQuery {
   134  	result := *q
   135  	if opts == nil {
   136  		return &result
   137  	}
   138  
   139  	restrictOpts := opts.RestrictQueryOptions
   140  	if restrictOpts == nil {
   141  		return &result
   142  	}
   143  
   144  	restrict := restrictOpts.GetRestrictByTag().GetMatchers()
   145  	if len(restrict) == 0 {
   146  		return &result
   147  	}
   148  
   149  	// Since must apply matchers will always be small (usually 1)
   150  	// it's better to not allocate intermediate datastructure and just
   151  	// perform n^2 matching.
   152  	existing := result.TagMatchers
   153  	for _, existingMatcher := range result.TagMatchers {
   154  		willBeOverridden := false
   155  		for _, matcher := range restrict {
   156  			if bytes.Equal(existingMatcher.Name, matcher.Name) {
   157  				willBeOverridden = true
   158  				break
   159  			}
   160  		}
   161  
   162  		if willBeOverridden {
   163  			// We'll override this when we append the restrict matchers.
   164  			continue
   165  		}
   166  
   167  		existing = append(existing, existingMatcher)
   168  	}
   169  
   170  	// Now append the must apply matchers.
   171  	result.TagMatchers = append(existing, restrict...)
   172  	return &result
   173  }
   174  
   175  func (q *FetchQuery) String() string {
   176  	return q.Raw
   177  }