github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/metrics/rules/match_result.go (about) 1 // Copyright (c) 2020 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 rules 22 23 import ( 24 "bytes" 25 26 "github.com/m3db/m3/src/cluster/kv" 27 "github.com/m3db/m3/src/metrics/metadata" 28 "github.com/m3db/m3/src/metrics/metric/id" 29 ) 30 31 var ( 32 // EmptyMatchResult is the result when no matches were found. 33 EmptyMatchResult = NewMatchResult( 34 kv.UninitializedVersion, 35 timeNanosMax, 36 metadata.DefaultStagedMetadatas, 37 nil, 38 false, 39 ) 40 ) 41 42 // IDWithMetadatas is a pair of metric ID and the associated staged metadatas. 43 type IDWithMetadatas struct { 44 ID []byte 45 Metadatas metadata.StagedMetadatas 46 } 47 48 // IDWithMetadatasByIDAsc sorts a list of ID with metadatas by metric ID in ascending order. 49 type IDWithMetadatasByIDAsc []IDWithMetadatas 50 51 func (a IDWithMetadatasByIDAsc) Len() int { return len(a) } 52 func (a IDWithMetadatasByIDAsc) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 53 func (a IDWithMetadatasByIDAsc) Less(i, j int) bool { return bytes.Compare(a[i].ID, a[j].ID) < 0 } 54 55 // MatchResult represents a match result. 56 type MatchResult struct { 57 version int 58 expireAtNanos int64 59 // This contains the matched staged metadatas where the metric ID 60 // remains the same during the first step of the aggregation process, 61 // which includes all mapping rule matches, as well as rollup rule 62 // matches where the first pipeline operation is not a rollup operation. 63 forExistingID metadata.StagedMetadatas 64 // This contains the match result where a new metric ID is used 65 // during the first step of the aggregation process, which is usually 66 // produced by a rollup rule whose rollup pipeline contains a rollup operation 67 // as its first step. 68 forNewRollupIDs []IDWithMetadatas 69 keepOriginal bool 70 } 71 72 // MatchOptions are request level options for each Match. 73 type MatchOptions struct { 74 NameAndTagsFn id.NameAndTagsFn 75 SortedTagIteratorFn id.SortedTagIteratorFn 76 } 77 78 // NewMatchResult creates a new match result. 79 func NewMatchResult( 80 version int, 81 expireAtNanos int64, 82 forExistingID metadata.StagedMetadatas, 83 forNewRollupIDs []IDWithMetadatas, 84 keepOriginal bool, 85 ) MatchResult { 86 return MatchResult{ 87 version: version, 88 expireAtNanos: expireAtNanos, 89 forExistingID: forExistingID, 90 forNewRollupIDs: forNewRollupIDs, 91 keepOriginal: keepOriginal, 92 } 93 } 94 95 // Version returns the version of the match result. 96 func (r *MatchResult) Version() int { return r.version } 97 98 // ExpireAtNanos returns the expiration time of the match result in nanoseconds. 99 func (r *MatchResult) ExpireAtNanos() int64 { return r.expireAtNanos } 100 101 // HasExpired returns whether the match result has expired for a given time. 102 func (r *MatchResult) HasExpired(timeNanos int64) bool { return r.expireAtNanos <= timeNanos } 103 104 // NumNewRollupIDs returns the number of new rollup metric IDs generated as a 105 // result of rule matching. 106 func (r *MatchResult) NumNewRollupIDs() int { return len(r.forNewRollupIDs) } 107 108 // ForExistingIDAt returns the staged metadatas for existing ID at a given time. 109 func (r *MatchResult) ForExistingIDAt(timeNanos int64) metadata.StagedMetadatas { 110 return activeStagedMetadatasAt(r.forExistingID, timeNanos) 111 } 112 113 // ForNewRollupIDsAt returns the the new rollup ID alongside its staged metadatas 114 // for a given index at a given time. 115 func (r *MatchResult) ForNewRollupIDsAt(idx int, timeNanos int64) IDWithMetadatas { 116 forNewRollupID := r.forNewRollupIDs[idx] 117 metadatas := activeStagedMetadatasAt(forNewRollupID.Metadatas, timeNanos) 118 return IDWithMetadatas{ID: forNewRollupID.ID, Metadatas: metadatas} 119 } 120 121 // KeepOriginal returns true if the original source metric for a rollup rule 122 // should be kept, and false if it should be dropped. 123 func (r *MatchResult) KeepOriginal() bool { 124 return r.keepOriginal 125 } 126 127 // activeStagedMetadatasAt returns the active staged metadatas at a given time, assuming 128 // the input list of staged metadatas are sorted by cutover time in ascending order. 129 func activeStagedMetadatasAt( 130 metadatas metadata.StagedMetadatas, 131 timeNanos int64, 132 ) metadata.StagedMetadatas { 133 for idx := len(metadatas) - 1; idx >= 0; idx-- { 134 if metadatas[idx].CutoverNanos <= timeNanos { 135 return metadatas[idx:] 136 } 137 } 138 return metadatas 139 }