github.com/alibaba/ilogtail/pkg@v0.0.0-20250526110833-c53b480d046c/models/metrics.go (about)

     1  // Copyright 2022 iLogtail Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package models
    16  
    17  import (
    18  	"fmt"
    19  	"strings"
    20  )
    21  
    22  type MetricType int
    23  
    24  const (
    25  	// Common metrics types
    26  	_ MetricType = iota
    27  	MetricTypeUntyped
    28  	MetricTypeCounter
    29  	MetricTypeGauge
    30  	MetricTypeHistogram
    31  	MetricTypeSummary
    32  
    33  	// Extended metrics types
    34  	MetricTypeMeter       // In bytetsd, meter is an extension of the counter type, which contains a counter value and a rate value within a period
    35  	MetricTypeRateCounter // In bytetsd, ratecounter is an extension of the counter type, which contains a rate value within a period
    36  )
    37  
    38  var (
    39  	MetricTypeTexts = map[MetricType]string{
    40  		MetricTypeCounter:     "Counter",
    41  		MetricTypeGauge:       "Gauge",
    42  		MetricTypeHistogram:   "Histogram",
    43  		MetricTypeSummary:     "Summary",
    44  		MetricTypeUntyped:     "Untyped",
    45  		MetricTypeMeter:       "Meter",
    46  		MetricTypeRateCounter: "RateCounter",
    47  	}
    48  
    49  	MetricTypeValues = map[string]MetricType{
    50  		"Counter":     MetricTypeCounter,
    51  		"Gauge":       MetricTypeGauge,
    52  		"Histogram":   MetricTypeHistogram,
    53  		"Summary":     MetricTypeSummary,
    54  		"Untyped":     MetricTypeUntyped,
    55  		"Meter":       MetricTypeMeter,
    56  		"RateCounter": MetricTypeRateCounter,
    57  	}
    58  
    59  	emptyMetricValue = &EmptyMetricValue{}
    60  )
    61  
    62  type MetricValue interface {
    63  	IsSingleValue() bool
    64  
    65  	IsMultiValues() bool
    66  
    67  	GetSingleValue() float64
    68  
    69  	GetMultiValues() MetricFloatValues
    70  }
    71  
    72  type MetricSingleValue struct {
    73  	Value float64
    74  }
    75  
    76  func (v *MetricSingleValue) IsSingleValue() bool {
    77  	return true
    78  }
    79  
    80  func (v *MetricSingleValue) IsMultiValues() bool {
    81  	return false
    82  }
    83  
    84  func (v *MetricSingleValue) GetSingleValue() float64 {
    85  	if v != nil {
    86  		return v.Value
    87  	}
    88  	return 0
    89  }
    90  
    91  func (v *MetricSingleValue) GetMultiValues() MetricFloatValues {
    92  	return NilFloatValues
    93  }
    94  
    95  type MetricMultiValue struct {
    96  	Values MetricFloatValues
    97  }
    98  
    99  func (v *MetricMultiValue) Add(key string, value float64) {
   100  	v.Values.Add(key, value)
   101  }
   102  
   103  func (v *MetricMultiValue) IsSingleValue() bool {
   104  	return false
   105  }
   106  
   107  func (v *MetricMultiValue) IsMultiValues() bool {
   108  	return true
   109  }
   110  
   111  func (v *MetricMultiValue) GetSingleValue() float64 {
   112  	return 0
   113  }
   114  
   115  func (v *MetricMultiValue) GetMultiValues() MetricFloatValues {
   116  	if v != nil && v.Values != nil {
   117  		return v.Values
   118  	}
   119  	return NilFloatValues
   120  }
   121  
   122  type EmptyMetricValue struct {
   123  }
   124  
   125  func (v *EmptyMetricValue) IsSingleValue() bool {
   126  	return false
   127  }
   128  
   129  func (v *EmptyMetricValue) IsMultiValues() bool {
   130  	return false
   131  }
   132  
   133  func (v *EmptyMetricValue) GetSingleValue() float64 {
   134  	return 0
   135  }
   136  
   137  func (v *EmptyMetricValue) GetMultiValues() MetricFloatValues {
   138  	return NilFloatValues
   139  }
   140  
   141  type MetricFloatValues interface {
   142  	KeyValues[float64]
   143  }
   144  
   145  // MetricTypedValues In TSDB such as influxdb,
   146  // its fields not only have numeric types, also string, bool, and array types.
   147  // MetricTypedValues is used to define types other than numeric values.
   148  type MetricTypedValues interface {
   149  	KeyValues[*TypedValue]
   150  }
   151  
   152  // Defines a Metric which has one or more timeseries.  The following is a
   153  // brief summary of the Metric data model.  For more details, see:
   154  // https://github.com/alibaba/ilogtail/discussions/518
   155  // - Metric is composed of a metadata and data.
   156  // - Metadata part contains a name, description, unit, tags
   157  // - Data is one of the possible types (Counter, Gauge, Histogram, Summary).
   158  type Metric struct {
   159  	Name              string
   160  	Unit              string
   161  	Description       string
   162  	Timestamp         uint64
   163  	ObservedTimestamp uint64
   164  
   165  	Tags       Tags
   166  	MetricType MetricType
   167  	Value      MetricValue
   168  	TypedValue MetricTypedValues
   169  }
   170  
   171  func (m *Metric) GetName() string {
   172  	if m != nil {
   173  		return m.Name
   174  	}
   175  	return ""
   176  }
   177  
   178  func (m *Metric) SetName(name string) {
   179  	if m != nil {
   180  		m.Name = name
   181  	}
   182  }
   183  
   184  func (m *Metric) GetTags() Tags {
   185  	if m != nil {
   186  		return m.Tags
   187  	}
   188  	return NilStringValues
   189  }
   190  
   191  func (m *Metric) GetType() EventType {
   192  	return EventTypeMetric
   193  }
   194  
   195  func (m *Metric) GetTimestamp() uint64 {
   196  	if m != nil {
   197  		return m.Timestamp
   198  	}
   199  	return 0
   200  }
   201  
   202  func (m *Metric) GetObservedTimestamp() uint64 {
   203  	if m != nil {
   204  		return m.ObservedTimestamp
   205  	}
   206  	return 0
   207  }
   208  
   209  func (m *Metric) SetObservedTimestamp(timestamp uint64) {
   210  	if m != nil {
   211  		m.ObservedTimestamp = timestamp
   212  	}
   213  }
   214  
   215  func (m *Metric) GetMetricType() MetricType {
   216  	if m != nil {
   217  		return m.MetricType
   218  	}
   219  	return MetricTypeUntyped
   220  }
   221  
   222  func (m *Metric) GetUnit() string {
   223  	if m != nil {
   224  		return m.Unit
   225  	}
   226  	return ""
   227  }
   228  
   229  func (m *Metric) GetDescription() string {
   230  	if m != nil {
   231  		return m.Description
   232  	}
   233  	return ""
   234  }
   235  
   236  func (m *Metric) GetValue() MetricValue {
   237  	if m != nil && m.Value != nil {
   238  		return m.Value
   239  	}
   240  	return emptyMetricValue
   241  }
   242  
   243  func (m *Metric) GetTypedValue() MetricTypedValues {
   244  	if m != nil && m.TypedValue != nil {
   245  		return m.TypedValue
   246  	}
   247  	return NilTypedValues
   248  }
   249  
   250  func (m *Metric) GetSize() int64 {
   251  	return int64(len(m.String()))
   252  }
   253  
   254  func (m *Metric) Clone() PipelineEvent {
   255  	if m != nil {
   256  		return &Metric{
   257  			Name:              m.Name,
   258  			Description:       m.Description,
   259  			Timestamp:         m.Timestamp,
   260  			ObservedTimestamp: m.ObservedTimestamp,
   261  			Tags:              m.Tags,
   262  			MetricType:        m.MetricType,
   263  			Value:             m.Value,
   264  			TypedValue:        m.TypedValue,
   265  		}
   266  	}
   267  	return nil
   268  }
   269  
   270  func (m *Metric) String() string {
   271  	var builder strings.Builder
   272  	builder.WriteString(m.GetName())
   273  
   274  	tags := m.GetTags()
   275  
   276  	if tags.Len() > 0 {
   277  		builder.WriteByte('{')
   278  		sortedTags := tags.SortTo(nil)
   279  		for i, tags := range sortedTags {
   280  			builder.WriteString(fmt.Sprintf("%v=%v", tags.Key, tags.Value))
   281  			if i < len(sortedTags)-1 {
   282  				builder.WriteString(", ")
   283  			}
   284  		}
   285  		builder.WriteString("}")
   286  	}
   287  
   288  	builder.WriteString("[Type=")
   289  	builder.WriteString(MetricTypeTexts[m.MetricType])
   290  	builder.WriteString(", Ts=")
   291  	builder.WriteString(fmt.Sprintf("%v", m.Timestamp))
   292  	builder.WriteString("] ")
   293  
   294  	if m.Value.IsSingleValue() {
   295  		builder.WriteString(fmt.Sprintf("value=%v", m.Value.GetSingleValue()))
   296  	} else {
   297  		sortedValues := m.Value.GetMultiValues().SortTo(nil)
   298  		for i, values := range sortedValues {
   299  			builder.WriteString(fmt.Sprintf("%v=%v", values.Key, values))
   300  			if i < len(sortedValues)-1 {
   301  				builder.WriteString(", ")
   302  			}
   303  		}
   304  	}
   305  
   306  	return builder.String()
   307  }