fix(database/influxdb): replace invisible chars and whitespaces with space (#235)
This fixes issues where users use '\n' in tag values (e.g. the owner) that is incompatible with InfluxDB's Line protocol.
This commit is contained in:
parent
9e13f41143
commit
ef3ee358d1
|
@ -1,8 +1,10 @@
|
||||||
package influxdb
|
package influxdb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
"github.com/bdlm/log"
|
"github.com/bdlm/log"
|
||||||
"github.com/influxdata/influxdb1-client/models"
|
"github.com/influxdata/influxdb1-client/models"
|
||||||
|
@ -94,6 +96,25 @@ func Connect(configuration map[string]interface{}) (database.Connection, error)
|
||||||
return db, nil
|
return db, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sanitizeValues(tags models.Tags) models.Tags {
|
||||||
|
// https://docs.influxdata.com/influxdb/v2/reference/syntax/line-protocol/
|
||||||
|
// Line protocol does not support the newline character \n in tag or field values.
|
||||||
|
// To be safe, remove all non-printable characters and spaces except ASCII space and U+0020.
|
||||||
|
for _, tag := range tags {
|
||||||
|
cleaned_value := strings.Map(func(r rune) rune {
|
||||||
|
if unicode.IsPrint(r) {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
return ' '
|
||||||
|
}, string(tag.Value))
|
||||||
|
|
||||||
|
if cleaned_value != string(tag.Value) {
|
||||||
|
tags.SetString(string(tag.Key), cleaned_value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tags
|
||||||
|
}
|
||||||
|
|
||||||
func (conn *Connection) addPoint(name string, tags models.Tags, fields models.Fields, t ...time.Time) {
|
func (conn *Connection) addPoint(name string, tags models.Tags, fields models.Fields, t ...time.Time) {
|
||||||
if configTags := conn.config.Tags(); configTags != nil {
|
if configTags := conn.config.Tags(); configTags != nil {
|
||||||
for tag, valueInterface := range configTags {
|
for tag, valueInterface := range configTags {
|
||||||
|
@ -107,6 +128,9 @@ func (conn *Connection) addPoint(name string, tags models.Tags, fields models.Fi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tags = sanitizeValues(tags)
|
||||||
|
|
||||||
point, err := client.NewPoint(name, tags.Map(), fields, t...)
|
point, err := client.NewPoint(name, tags.Map(), fields, t...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicf("could not save points: %s", err)
|
log.Panicf("could not save points: %s", err)
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/influxdata/influxdb1-client/models"
|
"github.com/influxdata/influxdb1-client/models"
|
||||||
"github.com/influxdata/influxdb1-client/v2"
|
client "github.com/influxdata/influxdb1-client/v2"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
@ -98,3 +98,41 @@ func TestAddPoint(t *testing.T) {
|
||||||
connection.addPoint("name", models.Tags{}, nil, time.Now())
|
connection.addPoint("name", models.Tags{}, nil, time.Now())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAddPointWithInvalidCharacters(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
connection := &Connection{
|
||||||
|
config: map[string]interface{}{},
|
||||||
|
points: make(chan *client.Point, 1),
|
||||||
|
}
|
||||||
|
|
||||||
|
tagsOrigin := models.Tags{}
|
||||||
|
tagsOrigin.SetString("owner", "\u00a0this owner\nuses invalid chars\t")
|
||||||
|
|
||||||
|
connection.addPoint("name", tagsOrigin, models.Fields{"clients.total": 10}, time.Now())
|
||||||
|
point := <-connection.points
|
||||||
|
assert.NotNil(point)
|
||||||
|
tags := point.Tags()
|
||||||
|
assert.NotNil(tags)
|
||||||
|
assert.Equal(tags["owner"], " this owner uses invalid chars ")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddPointWithValidCharacters(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
|
||||||
|
connection := &Connection{
|
||||||
|
config: map[string]interface{}{},
|
||||||
|
points: make(chan *client.Point, 1),
|
||||||
|
}
|
||||||
|
|
||||||
|
tagsOrigin := models.Tags{}
|
||||||
|
tagsOrigin.SetString("owner", "📶this owner uses only\u0020valid chars🛜")
|
||||||
|
|
||||||
|
connection.addPoint("name", tagsOrigin, models.Fields{"clients.total": 10}, time.Now())
|
||||||
|
point := <-connection.points
|
||||||
|
assert.NotNil(point)
|
||||||
|
tags := point.Tags()
|
||||||
|
assert.NotNil(tags)
|
||||||
|
assert.Equal(tags["owner"], "📶this owner uses only\u0020valid chars🛜")
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue