core/base/metric_item.go (112 lines of code) (raw):
// Copyright 1999-2020 Alibaba Group Holding Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package base
import (
"errors"
"fmt"
"strconv"
"strings"
"github.com/alibaba/sentinel-golang/util"
)
const metricPartSeparator = "|"
// MetricItem represents the data of metric log per line.
type MetricItem struct {
Resource string
Classification int32
Timestamp uint64
PassQps uint64
BlockQps uint64
CompleteQps uint64
ErrorQps uint64
AvgRt uint64
OccupiedPassQps uint64
Concurrency uint32
}
type MetricItemRetriever interface {
MetricsOnCondition(predicate TimePredicate) []*MetricItem
}
func (m *MetricItem) ToFatString() (string, error) {
b := strings.Builder{}
timeStr := util.FormatTimeMillis(m.Timestamp)
// All "|" in the resource name will be replaced with "_"
finalName := strings.ReplaceAll(m.Resource, "|", "_")
_, err := fmt.Fprintf(&b, "%d|%s|%s|%d|%d|%d|%d|%d|%d|%d|%d",
m.Timestamp, timeStr, finalName, m.PassQps,
m.BlockQps, m.CompleteQps, m.ErrorQps, m.AvgRt,
m.OccupiedPassQps, m.Concurrency, m.Classification)
if err != nil {
return "", err
}
return b.String(), nil
}
func (m *MetricItem) ToThinString() (string, error) {
b := strings.Builder{}
finalName := strings.ReplaceAll(m.Resource, "|", "_")
_, err := fmt.Fprintf(&b, "%d|%s|%d|%d|%d|%d|%d|%d|%d|%d",
m.Timestamp, finalName, m.PassQps,
m.BlockQps, m.CompleteQps, m.ErrorQps, m.AvgRt,
m.OccupiedPassQps, m.Concurrency, m.Classification)
if err != nil {
return "", err
}
return b.String(), nil
}
func MetricItemFromFatString(line string) (*MetricItem, error) {
if len(line) == 0 {
return nil, errors.New("invalid metric line: empty string")
}
item := &MetricItem{}
arr := strings.Split(line, metricPartSeparator)
if len(arr) < 8 {
return nil, errors.New("invalid metric line: invalid format")
}
ts, err := strconv.ParseUint(arr[0], 10, 64)
if err != nil {
return nil, err
}
item.Timestamp = ts
item.Resource = arr[2]
p, err := strconv.ParseUint(arr[3], 10, 64)
if err != nil {
return nil, err
}
item.PassQps = p
b, err := strconv.ParseUint(arr[4], 10, 64)
if err != nil {
return nil, err
}
item.BlockQps = b
c, err := strconv.ParseUint(arr[5], 10, 64)
if err != nil {
return nil, err
}
item.CompleteQps = c
e, err := strconv.ParseUint(arr[6], 10, 64)
if err != nil {
return nil, err
}
item.ErrorQps = e
rt, err := strconv.ParseUint(arr[7], 10, 64)
if err != nil {
return nil, err
}
item.AvgRt = rt
if len(arr) >= 9 {
oc, err := strconv.ParseUint(arr[8], 10, 64)
if err != nil {
return nil, err
}
item.OccupiedPassQps = oc
}
if len(arr) >= 10 {
concurrency, err := strconv.ParseUint(arr[9], 10, 32)
if err != nil {
return nil, err
}
item.Concurrency = uint32(concurrency)
}
if len(arr) >= 11 {
cl, err := strconv.ParseInt(arr[10], 10, 32)
if err != nil {
return nil, err
}
item.Classification = int32(cl)
}
return item, nil
}