metricator/internal/application/parser.go

121 lines
2.7 KiB
Go

package application
import (
"log"
"strings"
"go.dev.pztrn.name/metricator/internal/models"
)
// Parses passed body and returns a map suitable for pushing into storage.
func (a *Application) parse(body string) map[string]models.Metric {
data := make(map[string]models.Metric)
// ToDo: switch to bytes buffer and maybe do not read body in caller?
splittedBody := strings.Split(body, "\n")
for _, line := range splittedBody {
// Prometheus line contains metric name and metric parameters defined
// in "{}".
var (
name, value string
params []string
)
// Skip empty lines.
if line == "" {
continue
}
// Check that line isn't commented. We should skip comments for now.
if strings.HasPrefix(line, "#") {
continue
}
log.Println("Analyzing line:", line)
// Check if we have parametrized metric. If no - push it to data map.
if !strings.Contains(line, "{") {
name = strings.Split(line, " ")[0]
value = strings.Split(line, " ")[1]
} else {
value = strings.Split(line, " ")[1]
name = strings.Split(line, "{")[0]
params = a.getParametersForPrometheusMetric(line)
for _, param := range params {
name += "/" + param
}
}
metric := models.NewMetric(name, "", params)
metric.SetValue(value)
data[name] = metric
}
log.Printf("Data parsed: %+v\n", data)
return data
}
// Parses passed line and returns a slice of strings with parameters parsed.
func (a *Application) getParametersForPrometheusMetric(line string) []string {
valuesString := strings.Split(strings.Split(line, "{")[1], "}")[0]
var (
params []string
paramName, paramValue string
paramNameFinished, paramValueStarted, paramValueFinished bool
)
for _, r := range valuesString {
if paramValueFinished && string(r) == "," {
params = append(params, paramName+":"+paramValue)
paramName, paramValue = "", ""
paramNameFinished, paramValueStarted, paramValueFinished = false, false, false
continue
}
// Sometimes nestif causes questions, like here. Is code below is
// "deply nested"? I think not. So:
// nolint:nestif
if !paramNameFinished {
if string(r) != "=" {
paramName += string(r)
continue
} else {
paramNameFinished = true
continue
}
} else {
if string(r) == "\"" && !paramValueStarted {
paramValueStarted = true
continue
}
if paramValueStarted && string(r) != "\"" {
paramValue += string(r)
continue
}
if paramValueStarted && string(r) == "\"" {
paramValueFinished = true
continue
}
}
}
if paramName != "" && paramValue != "" {
params = append(params, paramName+":"+paramValue)
}
return params
}