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  }