github.com/m3db/m3@v1.5.0/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 }