forked from grafana-cold-storage/metrictank
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinput.go
More file actions
81 lines (70 loc) · 2.54 KB
/
Copy pathinput.go
File metadata and controls
81 lines (70 loc) · 2.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
// Package in provides interfaces, concrete implementations, and utilities
// to ingest data into metrictank
package input
import (
"fmt"
"time"
"github.com/raintank/metrictank/idx"
"github.com/raintank/metrictank/mdata"
"github.com/raintank/metrictank/stats"
"github.com/raintank/metrictank/usage"
"github.com/raintank/worldping-api/pkg/log"
"gopkg.in/raintank/schema.v1"
)
type Handler interface {
Process(metric *schema.MetricData, partition int32)
}
// TODO: clever way to document all metrics for all different inputs
// Default is a base handler for a metrics packet, aimed to be embedded by concrete implementations
type DefaultHandler struct {
metricsReceived *stats.Counter32
MetricInvalid *stats.Counter32 // metric metric_invalid is a count of times a metric did not validate
MsgsAge *stats.Meter32 // in ms
pressureIdx *stats.Counter32
pressureTank *stats.Counter32
metrics mdata.Metrics
metricIndex idx.MetricIndex
usage *usage.Usage
}
func NewDefaultHandler(metrics mdata.Metrics, metricIndex idx.MetricIndex, usage *usage.Usage, input string) DefaultHandler {
return DefaultHandler{
metricsReceived: stats.NewCounter32(fmt.Sprintf("input.%s.metrics_received", input)),
MetricInvalid: stats.NewCounter32(fmt.Sprintf("input.%s.metric_invalid", input)),
MsgsAge: stats.NewMeter32(fmt.Sprintf("input.%s.message_age", input), false),
pressureIdx: stats.NewCounter32(fmt.Sprintf("input.%s.pressure.idx", input)),
pressureTank: stats.NewCounter32(fmt.Sprintf("input.%s.pressure.tank", input)),
metrics: metrics,
metricIndex: metricIndex,
usage: usage,
}
}
// process makes sure the data is stored and the metadata is in the index,
// and the usage is tracked, if enabled.
// concurrency-safe.
func (in DefaultHandler) Process(metric *schema.MetricData, partition int32) {
if metric == nil {
return
}
in.metricsReceived.Inc()
err := metric.Validate()
if err != nil {
in.MetricInvalid.Inc()
log.Debug("in: Invalid metric %s %v", err, metric)
return
}
if metric.Time == 0 {
in.MetricInvalid.Inc()
log.Warn("in: invalid metric. metric.Time is 0. %s", metric.Id)
return
}
pre := time.Now()
archive := in.metricIndex.AddOrUpdate(metric, partition)
in.pressureIdx.Add(int(time.Since(pre).Nanoseconds()))
pre = time.Now()
m := in.metrics.GetOrCreate(metric.Id, metric.Name, archive.SchemaId, archive.AggId)
m.Add(uint32(metric.Time), metric.Value)
if in.usage != nil {
in.usage.Add(metric.OrgId, metric.Id)
}
in.pressureTank.Add(int(time.Since(pre).Nanoseconds()))
}