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 }