176 lines
3.6 KiB
Go
176 lines
3.6 KiB
Go
|
package prometheus
|
||
|
|
||
|
import (
|
||
|
"strings"
|
||
|
"unicode"
|
||
|
|
||
|
"github.com/influxdata/telegraf"
|
||
|
dto "github.com/prometheus/client_model/go"
|
||
|
)
|
||
|
|
||
|
var FirstTable = &unicode.RangeTable{
|
||
|
R16: []unicode.Range16{
|
||
|
{0x0041, 0x005A, 1}, // A-Z
|
||
|
{0x005F, 0x005F, 1}, // _
|
||
|
{0x0061, 0x007A, 1}, // a-z
|
||
|
},
|
||
|
LatinOffset: 3,
|
||
|
}
|
||
|
|
||
|
var RestTable = &unicode.RangeTable{
|
||
|
R16: []unicode.Range16{
|
||
|
{0x0030, 0x0039, 1}, // 0-9
|
||
|
{0x0041, 0x005A, 1}, // A-Z
|
||
|
{0x005F, 0x005F, 1}, // _
|
||
|
{0x0061, 0x007A, 1}, // a-z
|
||
|
},
|
||
|
LatinOffset: 4,
|
||
|
}
|
||
|
|
||
|
func isValid(name string) bool {
|
||
|
if name == "" {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
for i, r := range name {
|
||
|
switch {
|
||
|
case i == 0:
|
||
|
if !unicode.In(r, FirstTable) {
|
||
|
return false
|
||
|
}
|
||
|
default:
|
||
|
if !unicode.In(r, RestTable) {
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
// SanitizeName check if the name is a valid Prometheus metric name and label
|
||
|
// name. If not, it attempts to replaces invalid runes with an underscore to
|
||
|
// create a valid name. Returns the metric name and true if the name is valid
|
||
|
// to use.
|
||
|
func SanitizeName(name string) (string, bool) {
|
||
|
if isValid(name) {
|
||
|
return name, true
|
||
|
}
|
||
|
|
||
|
var b strings.Builder
|
||
|
|
||
|
for i, r := range name {
|
||
|
switch {
|
||
|
case i == 0:
|
||
|
if unicode.In(r, FirstTable) {
|
||
|
b.WriteRune(r)
|
||
|
}
|
||
|
default:
|
||
|
if unicode.In(r, RestTable) {
|
||
|
b.WriteRune(r)
|
||
|
} else {
|
||
|
b.WriteString("_")
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
name = strings.Trim(b.String(), "_")
|
||
|
if name == "" {
|
||
|
return "", false
|
||
|
}
|
||
|
|
||
|
return name, true
|
||
|
}
|
||
|
|
||
|
// MetricName returns the Prometheus metric name.
|
||
|
func MetricName(measurement, fieldKey string, valueType telegraf.ValueType) string {
|
||
|
switch valueType {
|
||
|
case telegraf.Histogram, telegraf.Summary:
|
||
|
switch {
|
||
|
case strings.HasSuffix(fieldKey, "_bucket"):
|
||
|
fieldKey = strings.TrimSuffix(fieldKey, "_bucket")
|
||
|
case strings.HasSuffix(fieldKey, "_sum"):
|
||
|
fieldKey = strings.TrimSuffix(fieldKey, "_sum")
|
||
|
case strings.HasSuffix(fieldKey, "_count"):
|
||
|
fieldKey = strings.TrimSuffix(fieldKey, "_count")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if measurement == "prometheus" {
|
||
|
return fieldKey
|
||
|
}
|
||
|
return measurement + "_" + fieldKey
|
||
|
}
|
||
|
|
||
|
func MetricType(valueType telegraf.ValueType) *dto.MetricType {
|
||
|
switch valueType {
|
||
|
case telegraf.Counter:
|
||
|
return dto.MetricType_COUNTER.Enum()
|
||
|
case telegraf.Gauge:
|
||
|
return dto.MetricType_GAUGE.Enum()
|
||
|
case telegraf.Summary:
|
||
|
return dto.MetricType_SUMMARY.Enum()
|
||
|
case telegraf.Untyped:
|
||
|
return dto.MetricType_UNTYPED.Enum()
|
||
|
case telegraf.Histogram:
|
||
|
return dto.MetricType_HISTOGRAM.Enum()
|
||
|
default:
|
||
|
panic("unknown telegraf.ValueType")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// SampleValue converts a field value into a value suitable for a simple sample value.
|
||
|
func SampleValue(value interface{}) (float64, bool) {
|
||
|
switch v := value.(type) {
|
||
|
case float64:
|
||
|
return v, true
|
||
|
case int64:
|
||
|
return float64(v), true
|
||
|
case uint64:
|
||
|
return float64(v), true
|
||
|
case bool:
|
||
|
if v {
|
||
|
return 1.0, true
|
||
|
}
|
||
|
return 0.0, true
|
||
|
default:
|
||
|
return 0, false
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// SampleCount converts a field value into a count suitable for a metric family
|
||
|
// of the Histogram or Summary type.
|
||
|
func SampleCount(value interface{}) (uint64, bool) {
|
||
|
switch v := value.(type) {
|
||
|
case float64:
|
||
|
if v < 0 {
|
||
|
return 0, false
|
||
|
}
|
||
|
return uint64(v), true
|
||
|
case int64:
|
||
|
if v < 0 {
|
||
|
return 0, false
|
||
|
}
|
||
|
return uint64(v), true
|
||
|
case uint64:
|
||
|
return v, true
|
||
|
default:
|
||
|
return 0, false
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// SampleSum converts a field value into a sum suitable for a metric family
|
||
|
// of the Histogram or Summary type.
|
||
|
func SampleSum(value interface{}) (float64, bool) {
|
||
|
switch v := value.(type) {
|
||
|
case float64:
|
||
|
return v, true
|
||
|
case int64:
|
||
|
return float64(v), true
|
||
|
case uint64:
|
||
|
return float64(v), true
|
||
|
default:
|
||
|
return 0, false
|
||
|
}
|
||
|
}
|