github.com/GuanceCloud/cliutils@v1.1.21/point/lp.go (about) 1 // Unless explicitly stated otherwise all files in this repository are licensed 2 // under the MIT License. 3 // This product includes software developed at Guance Cloud (https://www.guance.com/). 4 // Copyright 2021-present Guance, Inc. 5 6 package point 7 8 import ( 9 "fmt" 10 "regexp" 11 "sort" 12 "time" 13 14 "github.com/influxdata/influxdb1-client/models" 15 ) 16 17 type Precision int 18 19 const ( 20 PrecNS Precision = iota // nano-second 21 PrecUS // micro-second 22 PrecMS // milli-second 23 PrecS // second 24 PrecM // minute 25 PrecH // hour 26 PrecD // day 27 PrecW // week 28 PrecDyn // dynamic precision 29 ) 30 31 func (p Precision) String() string { 32 switch p { 33 case PrecNS: 34 return "n" 35 case PrecUS: 36 return "u" 37 case PrecMS: 38 return "ms" 39 case PrecS: 40 return "s" 41 case PrecM: 42 return "m" 43 case PrecH: 44 return "h" 45 case PrecD: 46 return "d" 47 case PrecW: 48 return "w" 49 default: 50 return "unknown" 51 } 52 } 53 54 func PrecStr(s string) Precision { 55 switch s { 56 case "n": 57 return PrecNS 58 case "u": 59 return PrecUS 60 case "ms": 61 return PrecMS 62 case "s": 63 return PrecS 64 case "m": 65 return PrecM 66 case "h": 67 return PrecH 68 default: 69 return PrecNS 70 } 71 } 72 73 var sepRe = regexp.MustCompile(": ") 74 75 // simplifyLPError used to simplify original line-protocol parse error, the 76 // parse error will print origin data payload, for large payload, it's hard 77 // to read the error message. 78 func simplifyLPError(err error) error { 79 parts := sepRe.Split(err.Error(), -1) 80 if len(parts) != 2 { // return origin error 81 return err 82 } 83 84 return fmt.Errorf("lineproto parse error: %s", parts[1]) 85 } 86 87 // parseLPPoints parse line-protocol payload to Point. 88 func parseLPPoints(data []byte, c *cfg) ([]*Point, error) { 89 if len(data) == 0 { 90 return nil, fmt.Errorf("empty data") 91 } 92 93 if c == nil { 94 c = GetCfg() 95 defer PutCfg(c) 96 } 97 98 ptTime := c.t 99 if c.t.IsZero() { 100 ptTime = time.Now() 101 } 102 103 // NOTE: always parse point with precision ns, the caller should 104 // adjust the time according to specific precision setting. 105 lppts, err := models.ParsePointsWithPrecision(data, ptTime, "ns") 106 if err != nil { 107 return nil, fmt.Errorf("%w: %s. Origin data: %q", 108 ErrInvalidLineProtocol, err, data) 109 } 110 111 res := []*Point{} 112 chk := checker{cfg: c} 113 114 for _, x := range lppts { 115 if x == nil { 116 return nil, fmt.Errorf("line point is empty") 117 } 118 119 if c.extraTags != nil { 120 for _, t := range c.extraTags { 121 if !x.HasTag([]byte(t.Key)) { 122 x.AddTag(t.Key, t.GetS()) 123 } 124 } 125 } 126 127 pt := FromModelsLP(x) 128 if pt == nil { 129 continue 130 } 131 132 if c.keySorted { 133 kvs := KVs(pt.pt.Fields) 134 sort.Sort(kvs) 135 pt.pt.Fields = kvs 136 } 137 138 pt = chk.check(pt) 139 pt.pt.Warns = chk.warns 140 chk.reset() 141 142 // re-sort again: check may update pt.pt.Fields 143 if c.keySorted { 144 kvs := KVs(pt.pt.Fields) 145 sort.Sort(kvs) 146 pt.pt.Fields = kvs 147 } 148 149 res = append(res, pt) 150 } 151 152 return res, nil 153 }