github.com/alibaba/ilogtail/pkg@v0.0.0-20250526110833-c53b480d046c/protocol/converter/influxdb_metric.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 protocol 16 17 import ( 18 "context" 19 "fmt" 20 "strings" 21 "time" 22 23 "github.com/influxdata/line-protocol/v2/lineprotocol" 24 25 "github.com/alibaba/ilogtail/pkg/logger" 26 "github.com/alibaba/ilogtail/pkg/models" 27 "github.com/alibaba/ilogtail/pkg/protocol" 28 ) 29 30 // ConvertToInfluxdbProtocolStream converts @logGroup to []byte in the influxdb line protocol, 31 // @c.TagKeyRenameMap, @c.ProtocolKeyRenameMap param will be ignored, as they are not very suitable for metrics. 32 func (c *Converter) ConvertToInfluxdbProtocolStream(logGroup *protocol.LogGroup, targetFields []string) (stream [][]byte, values []map[string]string, err error) { 33 pooledBuf := GetPooledByteBuf() 34 35 var encoder lineprotocol.Encoder 36 encoder.SetBuffer(*pooledBuf) 37 encoder.Reset() 38 encoder.SetLax(true) 39 40 reader := newMetricReader() 41 defer reader.recycle() 42 43 for _, log := range logGroup.Logs { 44 err := reader.set(log) 45 if err != nil { 46 return nil, nil, err 47 } 48 49 metricName, fieldName := reader.readNames() 50 labels, err := reader.readSortedLabels() 51 if err != nil { 52 return nil, nil, err 53 } 54 55 v, err := reader.readValue() 56 if err != nil { 57 return nil, nil, err 58 } 59 value, ok := lineprotocol.NewValue(v) 60 if !ok { 61 return nil, nil, fmt.Errorf("unknown field value: %v", v) 62 } 63 timestamp, err := reader.readTimestamp() 64 if err != nil { 65 return nil, nil, err 66 } 67 68 encoder.StartLine(metricName) 69 for _, v := range labels { 70 encoder.AddTag(v.Key, v.Value) 71 } 72 encoder.AddField(fieldName, value) 73 encoder.EndLine(timestamp) 74 if encoder.Err() != nil { 75 return nil, nil, encoder.Err() 76 } 77 } 78 79 // we are batching logs in LogGroup, so only support find tags in the logGroup.LogTags 80 var desiredValues map[string]string 81 if len(targetFields) > 0 { 82 desiredValues = findTargetValuesInLogTags(targetFields, logGroup.LogTags) 83 } 84 85 return [][]byte{encoder.Bytes()}, []map[string]string{desiredValues}, nil 86 } 87 88 func (c *Converter) ConvertToInfluxdbProtocolStreamV2(groupEvents *models.PipelineGroupEvents, targetFields []string) (stream [][]byte, values []map[string]string, err error) { 89 pooledBuf := GetPooledByteBuf() 90 91 var encoder lineprotocol.Encoder 92 encoder.SetBuffer(*pooledBuf) 93 encoder.Reset() 94 encoder.SetLax(true) 95 96 for _, event := range groupEvents.Events { 97 metric, ok := event.(*models.Metric) 98 if !ok { 99 if c.IgnoreUnExpectedData { 100 logger.Warningf(context.Background(), "CONVERT_ALARM", "unsupported event type[%T] for converter with influxdb protocol", event) 101 continue 102 } 103 return nil, nil, fmt.Errorf("unsupported event type: %v", event.GetType()) 104 } 105 encoder.StartLine(metric.GetName()) 106 for _, v := range metric.GetTags().SortTo(nil) { 107 encoder.AddTag(v.Key, v.Value) 108 } 109 110 v := metric.GetValue() 111 if v.IsSingleValue() { 112 vv, _ := lineprotocol.FloatValue(v.GetSingleValue()) 113 encoder.AddField("value", vv) 114 } else if v.IsMultiValues() { 115 for name, value := range v.GetMultiValues().Iterator() { 116 vv, _ := lineprotocol.FloatValue(value) 117 encoder.AddField(name, vv) 118 } 119 } 120 121 fields := metric.GetTypedValue() 122 for name, value := range fields.Iterator() { 123 vv, ok := lineprotocol.NewValue(value.Value) 124 if !ok { 125 return nil, nil, fmt.Errorf("unsupported typed value:%+v", value) 126 } 127 encoder.AddField(name, vv) 128 } 129 130 t := int64(metric.GetTimestamp()) 131 encoder.EndLine(time.Unix(t/1e9, t%1e9)) 132 if encoder.Err() != nil { 133 return nil, nil, encoder.Err() 134 } 135 } 136 137 // we are batching events in groupEvents, so only support find tags in the groupEvents.Group 138 var desiredValues map[string]string 139 if len(targetFields) > 0 { 140 desiredValues = findTargetFieldsInGroup(targetFields, groupEvents.Group) 141 } 142 143 return [][]byte{encoder.Bytes()}, []map[string]string{desiredValues}, nil 144 } 145 146 func findTargetValuesInLogTags(targetFields []string, logTags []*protocol.LogTag) map[string]string { 147 if len(targetFields) == 0 { 148 return nil 149 } 150 151 tagMap := make(map[string]string, len(logTags)) 152 for _, logTag := range logTags { 153 var tagName string 154 if strings.HasPrefix(logTag.Key, tagPrefix) { 155 tagName = targetTagPrefix + logTag.Key[len(tagPrefix):] 156 } else { 157 tagName = logTag.Key 158 } 159 tagMap[tagName] = logTag.Value 160 } 161 162 desiredValue := make(map[string]string, len(targetFields)) 163 for _, field := range targetFields { 164 v, ok := tagMap[field] 165 if !ok { 166 continue 167 } 168 desiredValue[field] = v 169 } 170 return desiredValue 171 }