parent
c34babeaf8
commit
2e8fdb194c
@ -18,7 +18,7 @@ func (a *Application) parse(body string) map[string]models.Metric {
|
|||||||
// Prometheus line contains metric name and metric parameters defined
|
// Prometheus line contains metric name and metric parameters defined
|
||||||
// in "{}".
|
// in "{}".
|
||||||
var (
|
var (
|
||||||
name, value string
|
name string
|
||||||
params []string
|
params []string
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -27,29 +27,61 @@ func (a *Application) parse(body string) map[string]models.Metric {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that line isn't commented. We should skip comments for now.
|
log.Println("Analyzing line:", line)
|
||||||
|
|
||||||
|
name = a.getMetricName(line)
|
||||||
|
metric, found := data[name]
|
||||||
|
if !found {
|
||||||
|
metric = models.NewMetric(name, "", "", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If line is commented - then we have something about metric's description
|
||||||
|
// or type. It should be handled in special way - these metric will became
|
||||||
|
// "pseudometric" which will be used as template for next iterations. For
|
||||||
|
// example if HELP line was parsed first, then TYPE line will be parsed and
|
||||||
|
// data will be added to already existing metric. If next line which should
|
||||||
|
// represent metric itself contains parameters (e.g. "{instance='host1'}")
|
||||||
|
// then next code block will COPY populated with HELP and TYPE pesudometric
|
||||||
|
// and put it's value as new metric with different name (metric/instance:host1
|
||||||
|
// in this example).
|
||||||
if strings.HasPrefix(line, "#") {
|
if strings.HasPrefix(line, "#") {
|
||||||
|
switch strings.Split(line, " ")[1] {
|
||||||
|
case "HELP":
|
||||||
|
log.Println("Got HELP line")
|
||||||
|
|
||||||
|
metric.Description = a.getMetricDescription(line)
|
||||||
|
case "TYPE":
|
||||||
|
log.Println("Got TYPE line")
|
||||||
|
|
||||||
|
metric.Type = a.getMetricType(line)
|
||||||
|
}
|
||||||
|
|
||||||
|
data[name] = metric
|
||||||
|
|
||||||
|
// According to https://github.com/Showmax/prometheus-docs/blob/master/content/docs/instrumenting/exposition_formats.md
|
||||||
|
// HELP and TYPE lines should be printed before actual metric. Do not even
|
||||||
|
// report bugs regarding that!
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Println("Analyzing line:", line)
|
// Parametrized metrics should have own piece of love - we should
|
||||||
|
// add parameters to metric's name. This would also require metrics
|
||||||
|
// structure copying.
|
||||||
|
if strings.Contains(line, "{") {
|
||||||
|
newMetric := metric
|
||||||
|
|
||||||
// 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)
|
params = a.getParametersForPrometheusMetric(line)
|
||||||
|
|
||||||
for _, param := range params {
|
for _, param := range params {
|
||||||
name += "/" + param
|
newMetric.Name += "/" + param
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
metric := models.NewMetric(name, "", "", params)
|
metric = newMetric
|
||||||
metric.SetValue(value)
|
data[metric.Name] = metric
|
||||||
|
}
|
||||||
|
|
||||||
|
metric.Value = a.getMetricValue(line)
|
||||||
|
|
||||||
|
log.Printf("Got metric: %+v\n", metric)
|
||||||
|
|
||||||
data[name] = metric
|
data[name] = metric
|
||||||
}
|
}
|
||||||
@ -59,6 +91,38 @@ func (a *Application) parse(body string) map[string]models.Metric {
|
|||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gets metric description from passed line.
|
||||||
|
func (a *Application) getMetricDescription(line string) string {
|
||||||
|
return strings.Join(strings.Split(line, " ")[3:], " ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets metric name from passed line.
|
||||||
|
func (a *Application) getMetricName(line string) string {
|
||||||
|
var metricNameData string
|
||||||
|
|
||||||
|
if strings.HasPrefix(line, "#") {
|
||||||
|
metricNameData = strings.Split(line, " ")[2]
|
||||||
|
} else {
|
||||||
|
metricNameData = strings.Split(line, " ")[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Split(metricNameData, "{")[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets metric type from passed line.
|
||||||
|
func (a *Application) getMetricType(line string) string {
|
||||||
|
return strings.Split(line, " ")[3]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets metric value from passed line.
|
||||||
|
func (a *Application) getMetricValue(line string) string {
|
||||||
|
if strings.Contains(line, "}") {
|
||||||
|
return strings.Split(line, "} ")[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Split(line, " ")[1]
|
||||||
|
}
|
||||||
|
|
||||||
// Parses passed line and returns a slice of strings with parameters parsed.
|
// Parses passed line and returns a slice of strings with parameters parsed.
|
||||||
func (a *Application) getParametersForPrometheusMetric(line string) []string {
|
func (a *Application) getParametersForPrometheusMetric(line string) []string {
|
||||||
valuesString := strings.Split(strings.Split(line, "{")[1], "}")[0]
|
valuesString := strings.Split(strings.Split(line, "{")[1], "}")[0]
|
||||||
|
@ -74,8 +74,11 @@ func (s *Storage) Put(data map[string]models.Metric) {
|
|||||||
defer s.dataMutex.Unlock()
|
defer s.dataMutex.Unlock()
|
||||||
|
|
||||||
for k, v := range data {
|
for k, v := range data {
|
||||||
|
// We should not put valueless metrics.
|
||||||
|
if v.Value != "" {
|
||||||
s.data[k] = v
|
s.data[k] = v
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
log.Println("Put", len(data), "items in", s.name)
|
log.Println("Put", len(data), "items in", s.name)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user