chore(processors.converter): Cleanup code (#14744)

This commit is contained in:
Sven Rebhan 2024-02-12 15:43:01 +01:00 committed by GitHub
parent ad9b771e50
commit 298a1d4396
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 176 additions and 300 deletions

View File

@ -4,6 +4,7 @@ import (
"fmt"
"math"
"strconv"
"strings"
)
var ErrOutOfRange = strconv.ErrRange
@ -103,6 +104,9 @@ func ToFloat32(value interface{}) (float32, error) {
func ToUint64(value interface{}) (uint64, error) {
switch v := value.(type) {
case string:
if strings.HasPrefix(v, "0x") {
return strconv.ParseUint(strings.TrimPrefix(v, "0x"), 16, 64)
}
return strconv.ParseUint(v, 10, 64)
case []byte:
return strconv.ParseUint(string(v), 10, 64)
@ -167,6 +171,10 @@ func ToUint64(value interface{}) (uint64, error) {
func ToUint32(value interface{}) (uint32, error) {
switch v := value.(type) {
case string:
if strings.HasPrefix(v, "0x") {
x, err := strconv.ParseUint(strings.TrimPrefix(v, "0x"), 16, 32)
return uint32(x), err
}
x, err := strconv.ParseUint(v, 10, 32)
return uint32(x), err
case []byte:
@ -237,6 +245,10 @@ func ToUint32(value interface{}) (uint32, error) {
func ToUint16(value interface{}) (uint16, error) {
switch v := value.(type) {
case string:
if strings.HasPrefix(v, "0x") {
x, err := strconv.ParseUint(strings.TrimPrefix(v, "0x"), 16, 16)
return uint16(x), err
}
x, err := strconv.ParseUint(v, 10, 32)
return uint16(x), err
case []byte:
@ -310,6 +322,10 @@ func ToUint16(value interface{}) (uint16, error) {
func ToUint8(value interface{}) (uint8, error) {
switch v := value.(type) {
case string:
if strings.HasPrefix(v, "0x") {
x, err := strconv.ParseUint(strings.TrimPrefix(v, "0x"), 16, 8)
return uint8(x), err
}
x, err := strconv.ParseUint(v, 10, 32)
return uint8(x), err
case []byte:
@ -386,6 +402,9 @@ func ToUint8(value interface{}) (uint8, error) {
func ToInt64(value interface{}) (int64, error) {
switch v := value.(type) {
case string:
if strings.HasPrefix(v, "0x") {
return strconv.ParseInt(strings.TrimPrefix(v, "0x"), 16, 64)
}
return strconv.ParseInt(v, 10, 64)
case []byte:
return strconv.ParseInt(string(v), 10, 64)
@ -441,6 +460,10 @@ func ToInt64(value interface{}) (int64, error) {
func ToInt32(value interface{}) (int32, error) {
switch v := value.(type) {
case string:
if strings.HasPrefix(v, "0x") {
x, err := strconv.ParseInt(strings.TrimPrefix(v, "0x"), 16, 32)
return int32(x), err
}
x, err := strconv.ParseInt(v, 10, 32)
return int32(x), err
case []byte:
@ -508,6 +531,10 @@ func ToInt32(value interface{}) (int32, error) {
func ToInt16(value interface{}) (int16, error) {
switch v := value.(type) {
case string:
if strings.HasPrefix(v, "0x") {
x, err := strconv.ParseInt(strings.TrimPrefix(v, "0x"), 16, 16)
return int16(x), err
}
x, err := strconv.ParseInt(v, 10, 32)
return int16(x), err
case []byte:
@ -578,6 +605,10 @@ func ToInt16(value interface{}) (int16, error) {
func ToInt8(value interface{}) (int8, error) {
switch v := value.(type) {
case string:
if strings.HasPrefix(v, "0x") {
x, err := strconv.ParseInt(strings.TrimPrefix(v, "0x"), 16, 8)
return int8(x), err
}
x, err := strconv.ParseInt(v, 10, 32)
return int8(x), err
case []byte:

View File

@ -6,7 +6,6 @@ import (
"errors"
"math"
"math/big"
"strconv"
"strings"
"github.com/influxdata/telegraf"
@ -143,80 +142,46 @@ func (p *Converter) convertTags(metric telegraf.Metric) {
}
for key, value := range metric.Tags() {
if p.tagConversions.Measurement != nil && p.tagConversions.Measurement.Match(key) {
metric.RemoveTag(key)
switch {
case p.tagConversions.Measurement != nil && p.tagConversions.Measurement.Match(key):
metric.SetName(value)
continue
}
if p.tagConversions.String != nil && p.tagConversions.String.Match(key) {
metric.RemoveTag(key)
case p.tagConversions.String != nil && p.tagConversions.String.Match(key):
metric.AddField(key, value)
case p.tagConversions.Integer != nil && p.tagConversions.Integer.Match(key):
if v, err := toInteger(value); err != nil {
p.Log.Errorf("Converting to integer [%T] failed: %v", value, err)
} else {
metric.AddField(key, v)
}
case p.tagConversions.Unsigned != nil && p.tagConversions.Unsigned.Match(key):
if v, err := toUnsigned(value); err != nil {
p.Log.Errorf("Converting to unsigned [%T] failed: %v", value, err)
} else {
metric.AddField(key, v)
}
case p.tagConversions.Boolean != nil && p.tagConversions.Boolean.Match(key):
if v, err := internal.ToBool(value); err != nil {
p.Log.Errorf("Converting to boolean [%T] failed: %v", value, err)
} else {
metric.AddField(key, v)
}
case p.tagConversions.Float != nil && p.tagConversions.Float.Match(key):
if v, err := toFloat(value); err != nil {
p.Log.Errorf("Converting to float [%T] failed: %v", value, err)
} else {
metric.AddField(key, v)
}
case p.tagConversions.Timestamp != nil && p.tagConversions.Timestamp.Match(key):
if time, err := internal.ParseTimestamp(p.Tags.TimestampFormat, value, nil); err != nil {
p.Log.Errorf("Converting to timestamp [%T] failed: %v", value, err)
continue
} else {
metric.SetTime(time)
}
default:
continue
}
if p.tagConversions.Integer != nil && p.tagConversions.Integer.Match(key) {
v, ok := toInteger(value)
if !ok {
metric.RemoveTag(key)
p.Log.Errorf("error converting to integer [%T]: %v", value, value)
continue
}
metric.RemoveTag(key)
metric.AddField(key, v)
}
if p.tagConversions.Unsigned != nil && p.tagConversions.Unsigned.Match(key) {
v, ok := toUnsigned(value)
if !ok {
metric.RemoveTag(key)
p.Log.Errorf("error converting to unsigned [%T]: %v", value, value)
continue
}
metric.RemoveTag(key)
metric.AddField(key, v)
continue
}
if p.tagConversions.Boolean != nil && p.tagConversions.Boolean.Match(key) {
v, ok := toBool(value)
if !ok {
metric.RemoveTag(key)
p.Log.Errorf("error converting to boolean [%T]: %v", value, value)
continue
}
metric.RemoveTag(key)
metric.AddField(key, v)
continue
}
if p.tagConversions.Float != nil && p.tagConversions.Float.Match(key) {
v, ok := toFloat(value)
if !ok {
metric.RemoveTag(key)
p.Log.Errorf("error converting to float [%T]: %v", value, value)
continue
}
metric.RemoveTag(key)
metric.AddField(key, v)
continue
}
if p.tagConversions.Timestamp != nil && p.tagConversions.Timestamp.Match(key) {
time, err := internal.ParseTimestamp(p.Tags.TimestampFormat, value, nil)
if err != nil {
p.Log.Errorf("error converting to timestamp [%T]: %v", value, value)
continue
}
metric.RemoveTag(key)
metric.SetTime(time)
continue
}
metric.RemoveTag(key)
}
}
@ -227,277 +192,157 @@ func (p *Converter) convertFields(metric telegraf.Metric) {
}
for key, value := range metric.Fields() {
if p.fieldConversions.Measurement != nil && p.fieldConversions.Measurement.Match(key) {
v, ok := toString(value)
if !ok {
switch {
case p.fieldConversions.Measurement != nil && p.fieldConversions.Measurement.Match(key):
if v, err := internal.ToString(value); err != nil {
p.Log.Errorf("Converting to measurement [%T] failed: %v", value, err)
} else {
metric.SetName(v)
}
metric.RemoveField(key)
case p.fieldConversions.Tag != nil && p.fieldConversions.Tag.Match(key):
if v, err := internal.ToString(value); err != nil {
p.Log.Errorf("Converting to tag [%T] failed: %v", value, err)
} else {
metric.AddTag(key, v)
}
metric.RemoveField(key)
case p.fieldConversions.Float != nil && p.fieldConversions.Float.Match(key):
if v, err := toFloat(value); err != nil {
p.Log.Errorf("Converting to float [%T] failed: %v", value, err)
metric.RemoveField(key)
p.Log.Errorf("error converting to measurement [%T]: %v", value, value)
continue
} else {
metric.AddField(key, v)
}
metric.RemoveField(key)
metric.SetName(v)
continue
}
if p.fieldConversions.Tag != nil && p.fieldConversions.Tag.Match(key) {
v, ok := toString(value)
if !ok {
case p.fieldConversions.Integer != nil && p.fieldConversions.Integer.Match(key):
if v, err := toInteger(value); err != nil {
p.Log.Errorf("Converting to integer [%T] failed: %v", value, err)
metric.RemoveField(key)
p.Log.Errorf("error converting to tag [%T]: %v", value, value)
continue
} else {
metric.AddField(key, v)
}
metric.RemoveField(key)
metric.AddTag(key, v)
continue
}
if p.fieldConversions.Float != nil && p.fieldConversions.Float.Match(key) {
v, ok := toFloat(value)
if !ok {
case p.fieldConversions.Unsigned != nil && p.fieldConversions.Unsigned.Match(key):
if v, err := toUnsigned(value); err != nil {
p.Log.Errorf("Converting to unsigned [%T] failed: %v", value, err)
metric.RemoveField(key)
p.Log.Errorf("error converting to float [%T]: %v", value, value)
continue
} else {
metric.AddField(key, v)
}
metric.RemoveField(key)
metric.AddField(key, v)
continue
}
if p.fieldConversions.Integer != nil && p.fieldConversions.Integer.Match(key) {
v, ok := toInteger(value)
if !ok {
case p.fieldConversions.Boolean != nil && p.fieldConversions.Boolean.Match(key):
if v, err := internal.ToBool(value); err != nil {
p.Log.Errorf("Converting to bool [%T] failed: %v", value, err)
metric.RemoveField(key)
p.Log.Errorf("error converting to integer [%T]: %v", value, value)
continue
} else {
metric.AddField(key, v)
}
metric.RemoveField(key)
metric.AddField(key, v)
continue
}
if p.fieldConversions.Unsigned != nil && p.fieldConversions.Unsigned.Match(key) {
v, ok := toUnsigned(value)
if !ok {
case p.fieldConversions.String != nil && p.fieldConversions.String.Match(key):
if v, err := internal.ToString(value); err != nil {
p.Log.Errorf("Converting to string [%T] failed: %v", value, err)
metric.RemoveField(key)
p.Log.Errorf("error converting to unsigned [%T]: %v", value, value)
continue
} else {
metric.AddField(key, v)
}
metric.RemoveField(key)
metric.AddField(key, v)
continue
}
if p.fieldConversions.Boolean != nil && p.fieldConversions.Boolean.Match(key) {
v, ok := toBool(value)
if !ok {
case p.fieldConversions.Timestamp != nil && p.fieldConversions.Timestamp.Match(key):
if time, err := internal.ParseTimestamp(p.Fields.TimestampFormat, value, nil); err != nil {
p.Log.Errorf("Converting to timestamp [%T] failed: %v", value, err)
} else {
metric.SetTime(time)
metric.RemoveField(key)
p.Log.Errorf("error converting to bool [%T]: %v", value, value)
continue
}
metric.RemoveField(key)
metric.AddField(key, v)
continue
}
if p.fieldConversions.String != nil && p.fieldConversions.String.Match(key) {
v, ok := toString(value)
if !ok {
metric.RemoveField(key)
p.Log.Errorf("Error converting to string [%T]: %v", value, value)
continue
}
metric.RemoveField(key)
metric.AddField(key, v)
continue
}
if p.fieldConversions.Timestamp != nil && p.fieldConversions.Timestamp.Match(key) {
time, err := internal.ParseTimestamp(p.Fields.TimestampFormat, value, nil)
if err != nil {
p.Log.Errorf("error converting to timestamp [%T]: %v", value, value)
continue
}
metric.RemoveField(key)
metric.SetTime(time)
continue
}
}
}
func toBool(v interface{}) (val bool, ok bool) {
func toInteger(v interface{}) (int64, error) {
switch value := v.(type) {
case int64:
return value != 0, true
case uint64:
return value != 0, true
case float64:
return value != 0, true
case bool:
return value, true
case string:
result, err := strconv.ParseBool(value)
return result, err == nil
}
return false, false
}
func toInteger(v interface{}) (int64, bool) {
switch value := v.(type) {
case int64:
return value, true
case uint64:
if value <= uint64(math.MaxInt64) {
return int64(value), true
case float32:
if value < float32(math.MinInt64) {
return math.MinInt64, nil
}
return math.MaxInt64, true
if value > float32(math.MaxInt64) {
return math.MaxInt64, nil
}
return int64(math.Round(float64(value))), nil
case float64:
if value < float64(math.MinInt64) {
return math.MinInt64, true
} else if value > float64(math.MaxInt64) {
return math.MaxInt64, true
} else {
return int64(math.Round(value)), true
return math.MinInt64, nil
}
case bool:
if value {
return 1, true
if value > float64(math.MaxInt64) {
return math.MaxInt64, nil
}
return int64(math.Round(value)), nil
default:
if v, err := internal.ToInt64(value); err == nil {
return v, nil
}
return 0, true
case string:
result, err := strconv.ParseInt(value, 0, 64)
v, err := internal.ToFloat64(value)
if err != nil {
var result float64
var err error
if isHexadecimal(value) {
result, err = parseHexadecimal(value)
} else {
result, err = strconv.ParseFloat(value, 64)
}
if err != nil {
return 0, false
}
return toInteger(result)
return 0, err
}
return result, true
if v < float64(math.MinInt64) {
return math.MinInt64, nil
}
if v > float64(math.MaxInt64) {
return math.MaxInt64, nil
}
return int64(math.Round(v)), nil
}
return 0, false
}
func toUnsigned(v interface{}) (uint64, bool) {
func toUnsigned(v interface{}) (uint64, error) {
switch value := v.(type) {
case uint64:
return value, true
case int64:
case float32:
if value < 0 {
return 0, true
return 0, nil
}
return uint64(value), true
if value > float32(math.MaxUint64) {
return math.MaxUint64, nil
}
return uint64(math.Round(float64(value))), nil
case float64:
if value < 0.0 {
return 0, true
} else if value > float64(math.MaxUint64) {
return math.MaxUint64, true
} else {
return uint64(math.Round(value)), true
if value < 0 {
return 0, nil
}
case bool:
if value {
return 1, true
if value > float64(math.MaxUint64) {
return math.MaxUint64, nil
}
return uint64(math.Round(value)), nil
default:
if v, err := internal.ToUint64(value); err == nil {
return v, nil
}
return 0, true
case string:
result, err := strconv.ParseUint(value, 0, 64)
v, err := internal.ToFloat64(value)
if err != nil {
var result float64
var err error
if isHexadecimal(value) {
result, err = parseHexadecimal(value)
} else {
result, err = strconv.ParseFloat(value, 64)
}
if err != nil {
return 0, false
}
return toUnsigned(result)
}
return result, true
}
return 0, false
}
func toFloat(v interface{}) (float64, bool) {
switch value := v.(type) {
case int64:
return float64(value), true
case uint64:
return float64(value), true
case float64:
return value, true
case bool:
if value {
return 1.0, true
}
return 0.0, true
case string:
if isHexadecimal(value) {
result, err := parseHexadecimal(value)
return result, err == nil
return 0, err
}
result, err := strconv.ParseFloat(value, 64)
return result, err == nil
if v < 0 {
return 0, nil
}
if v > float64(math.MaxUint64) {
return math.MaxUint64, nil
}
return uint64(math.Round(v)), nil
}
return 0.0, false
}
func toString(v interface{}) (string, bool) {
switch value := v.(type) {
case int64:
return strconv.FormatInt(value, 10), true
case uint64:
return strconv.FormatUint(value, 10), true
case float64:
return strconv.FormatFloat(value, 'f', -1, 64), true
case bool:
return strconv.FormatBool(value), true
case string:
return value, true
func toFloat(v interface{}) (float64, error) {
if v, ok := v.(string); ok && strings.HasPrefix(v, "0x") {
var i big.Int
if _, success := i.SetString(v, 0); !success {
return 0, errors.New("unable to parse string to big int")
}
var f big.Float
f.SetInt(&i)
result, _ := f.Float64()
return result, nil
}
return "", false
}
func parseHexadecimal(value string) (float64, error) {
i := new(big.Int)
_, success := i.SetString(value, 0)
if !success {
return 0, errors.New("unable to parse string to big int")
}
f := new(big.Float).SetInt(i)
result, _ := f.Float64()
return result, nil
}
func isHexadecimal(value string) bool {
return len(value) >= 3 && strings.ToLower(value)[1] == 'x'
return internal.ToFloat64(v)
}
func init() {