add a demo plugin for prober (#586)
* add a demo plugin for prober * update demo plugin
This commit is contained in:
parent
322cbf27dc
commit
b055bc73c5
|
@ -4,15 +4,15 @@ import (
|
|||
// remote
|
||||
// _ "github.com/didi/nightingale/src/modules/monapi/plugins/api"
|
||||
// telegraf style
|
||||
_ "github.com/didi/nightingale/src/modules/monapi/plugins/elasticsearch"
|
||||
_ "github.com/didi/nightingale/src/modules/monapi/plugins/github"
|
||||
_ "github.com/didi/nightingale/src/modules/monapi/plugins/haproxy"
|
||||
_ "github.com/didi/nightingale/src/modules/monapi/plugins/mongodb"
|
||||
_ "github.com/didi/nightingale/src/modules/monapi/plugins/mysql"
|
||||
_ "github.com/didi/nightingale/src/modules/monapi/plugins/prometheus"
|
||||
_ "github.com/didi/nightingale/src/modules/monapi/plugins/redis"
|
||||
_ "github.com/didi/nightingale/src/modules/monapi/plugins/nginx"
|
||||
_ "github.com/didi/nightingale/src/modules/monapi/plugins/elasticsearch"
|
||||
_ "github.com/didi/nightingale/src/modules/monapi/plugins/prometheus"
|
||||
_ "github.com/didi/nightingale/src/modules/monapi/plugins/rabbitmq"
|
||||
_ "github.com/didi/nightingale/src/modules/monapi/plugins/haproxy"
|
||||
_ "github.com/didi/nightingale/src/modules/monapi/plugins/redis"
|
||||
_ "github.com/didi/nightingale/src/modules/monapi/plugins/tengine"
|
||||
_ "github.com/didi/nightingale/src/modules/monapi/plugins/zookeeper"
|
||||
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
package demo
|
||||
|
||||
import (
|
||||
"github.com/didi/nightingale/src/modules/monapi/collector"
|
||||
"github.com/didi/nightingale/src/modules/monapi/plugins/demo/demo"
|
||||
"github.com/didi/nightingale/src/toolkits/i18n"
|
||||
"github.com/influxdata/telegraf"
|
||||
)
|
||||
|
||||
func init() {
|
||||
collector.CollectorRegister(NewDemoCollector()) // for monapi
|
||||
i18n.DictRegister(langDict)
|
||||
}
|
||||
|
||||
type DemoCollector struct {
|
||||
*collector.BaseCollector
|
||||
}
|
||||
|
||||
func NewDemoCollector() *DemoCollector {
|
||||
return &DemoCollector{BaseCollector: collector.NewBaseCollector(
|
||||
"demo",
|
||||
collector.RemoteCategory,
|
||||
func() collector.TelegrafPlugin { return &DemoRule{} },
|
||||
)}
|
||||
}
|
||||
|
||||
var (
|
||||
langDict = map[string]map[string]string{
|
||||
"zh": map[string]string{
|
||||
"Period": "周期",
|
||||
"The period of the function, in seconds": "函数周期,单位 秒",
|
||||
"Count": "数量",
|
||||
"The Count of the series": "指标数量",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
type DemoRule struct {
|
||||
Period int `label:"Period" json:"period,required" description:"The period of the function, in seconds" default:"3600"`
|
||||
Count int `label:"Count" json:"count,required" enum:"[1, 2, 4, 8, 16]" description:"The Count of the series" default:"8"`
|
||||
}
|
||||
|
||||
func (p *DemoRule) Validate() error {
|
||||
if p.Period == 0 {
|
||||
p.Period = 3600
|
||||
}
|
||||
if p.Count == 0 {
|
||||
p.Period = 8
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *DemoRule) TelegrafInput() (telegraf.Input, error) {
|
||||
if err := p.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &demo.Demo{
|
||||
Period: p.Period,
|
||||
Count: p.Count,
|
||||
}, nil
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package demo
|
||||
|
||||
import (
|
||||
"math"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
)
|
||||
|
||||
type Demo struct {
|
||||
Period int `toml:"period"`
|
||||
Count int `toml:"count"`
|
||||
|
||||
initDone bool
|
||||
cos *cos
|
||||
}
|
||||
|
||||
func (d *Demo) SampleConfig() string {
|
||||
return `
|
||||
## The period of the function, in seconds
|
||||
period = 600
|
||||
## The Count of the series
|
||||
count = 3
|
||||
`
|
||||
}
|
||||
|
||||
func (d *Demo) Description() string {
|
||||
return "telegraf demo plugin"
|
||||
}
|
||||
|
||||
func (d *Demo) Init() {
|
||||
d.cos = &cos{
|
||||
period: float64(d.Period),
|
||||
offset: (d.Period / d.Count),
|
||||
}
|
||||
|
||||
d.initDone = true
|
||||
}
|
||||
|
||||
func (d *Demo) Gather(acc telegraf.Accumulator) error {
|
||||
if !d.initDone {
|
||||
d.Init()
|
||||
}
|
||||
|
||||
fields := make(map[string]interface{})
|
||||
tags := map[string]string{}
|
||||
for i := 0; i < d.Count; i++ {
|
||||
tags["n"] = strconv.Itoa(i)
|
||||
fields["value"] = d.cos.value(i)
|
||||
acc.AddFields("demo", fields, tags)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type cos struct {
|
||||
period float64
|
||||
offset int
|
||||
}
|
||||
|
||||
func (c *cos) value(i int) float64 {
|
||||
return math.Cos(2 * math.Pi * (float64(time.Now().Unix()+int64(c.offset*i)) / c.period))
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package demo
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/didi/nightingale/src/modules/monapi/plugins"
|
||||
)
|
||||
|
||||
func TestCollect(t *testing.T) {
|
||||
plugins.PluginTest(t, &DemoRule{
|
||||
Period: 3600,
|
||||
Count: 10,
|
||||
})
|
||||
}
|
|
@ -6,9 +6,7 @@ import (
|
|||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/didi/nightingale/src/common/dataobj"
|
||||
"github.com/didi/nightingale/src/modules/prober/manager"
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/didi/nightingale/src/modules/monapi/plugins"
|
||||
)
|
||||
|
||||
const sampleTextFormat = `# HELP test_metric An untyped metric with a timestamp
|
||||
|
@ -50,39 +48,7 @@ func TestCollect(t *testing.T) {
|
|||
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, sampleTextFormat) }))
|
||||
defer s.Close()
|
||||
|
||||
PluginTest(t, &PrometheusRule{
|
||||
plugins.PluginTest(t, &PrometheusRule{
|
||||
URLs: []string{s.URL},
|
||||
})
|
||||
}
|
||||
|
||||
type telegrafPlugin interface {
|
||||
TelegrafInput() (telegraf.Input, error)
|
||||
}
|
||||
|
||||
func PluginTest(t *testing.T, plugin telegrafPlugin) telegraf.Input {
|
||||
input, err := plugin.TelegrafInput()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
PluginInputTest(t, input)
|
||||
|
||||
return input
|
||||
}
|
||||
|
||||
func PluginInputTest(t *testing.T, input telegraf.Input) {
|
||||
metrics := []*dataobj.MetricValue{}
|
||||
|
||||
acc, err := manager.NewAccumulator(manager.AccumulatorOptions{Name: "plugin-test", Metrics: &metrics})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if err = input.Gather(acc); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
for k, v := range metrics {
|
||||
t.Logf("%d %s %s %f", k, v.CounterType, v.PK(), v.Value)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,11 @@ package plugins
|
|||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/didi/nightingale/src/common/dataobj"
|
||||
"github.com/didi/nightingale/src/modules/prober/manager"
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/toolkits/pkg/logger"
|
||||
)
|
||||
|
||||
|
@ -60,3 +64,35 @@ func SetValue(in interface{}, value interface{}, fields ...string) error {
|
|||
rv.Set(reflect.Indirect(reflect.ValueOf(value)))
|
||||
return nil
|
||||
}
|
||||
|
||||
type telegrafPlugin interface {
|
||||
TelegrafInput() (telegraf.Input, error)
|
||||
}
|
||||
|
||||
func PluginTest(t *testing.T, plugin telegrafPlugin) telegraf.Input {
|
||||
input, err := plugin.TelegrafInput()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
PluginInputTest(t, input)
|
||||
|
||||
return input
|
||||
}
|
||||
|
||||
func PluginInputTest(t *testing.T, input telegraf.Input) {
|
||||
metrics := []*dataobj.MetricValue{}
|
||||
|
||||
acc, err := manager.NewAccumulator(manager.AccumulatorOptions{Name: "plugin-test", Metrics: &metrics})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if err = input.Gather(acc); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
for k, v := range metrics {
|
||||
t.Logf("%d %s %s %f", k, v.CounterType, v.PK(), v.Value)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,20 +5,39 @@ import (
|
|||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/didi/nightingale/src/models"
|
||||
"github.com/didi/nightingale/src/modules/monapi/plugins/prometheus"
|
||||
"github.com/didi/nightingale/src/modules/monapi/collector"
|
||||
"github.com/didi/nightingale/src/modules/prober/config"
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/plugins/inputs/prometheus"
|
||||
)
|
||||
|
||||
const sampleTextFormat = `
|
||||
# HELP go_goroutines Number of goroutines that currently exist.
|
||||
# TYPE go_goroutines gauge
|
||||
go_goroutines 15 1490802350000
|
||||
# HELP test_guage guage
|
||||
# TYPE test_guage gauge
|
||||
test_guauge{label="1"} 1.1
|
||||
test_guauge{label="2"} 1.2
|
||||
test_guauge{label="3"} 1.3
|
||||
`
|
||||
|
||||
func TestManager(t *testing.T) {
|
||||
collector.CollectorRegister(&fakeCollector{BaseCollector: collector.NewBaseCollector(
|
||||
"fake",
|
||||
collector.RemoteCategory,
|
||||
func() collector.TelegrafPlugin { return &fakeRule{} },
|
||||
)})
|
||||
|
||||
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, sampleTextFormat) }))
|
||||
defer s.Close()
|
||||
|
||||
promRule := prometheus.PrometheusRule{URLs: []string{s.URL}}
|
||||
|
||||
b, err := json.Marshal(promRule)
|
||||
b, err := json.Marshal(fakeRule{URLs: []string{s.URL}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -28,7 +47,7 @@ func TestManager(t *testing.T) {
|
|||
Nid: 2,
|
||||
Step: 3,
|
||||
Timeout: 4,
|
||||
CollectType: "prometheus",
|
||||
CollectType: "fake",
|
||||
Name: "prom-test",
|
||||
Region: "default",
|
||||
Data: json.RawMessage(b),
|
||||
|
@ -54,13 +73,46 @@ func TestManager(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
const sampleTextFormat = `
|
||||
# HELP go_goroutines Number of goroutines that currently exist.
|
||||
# TYPE go_goroutines gauge
|
||||
go_goroutines 15 1490802350000
|
||||
# HELP test_guage guage
|
||||
# TYPE test_guage gauge
|
||||
test_guauge{label="1"} 1.1
|
||||
test_guauge{label="2"} 1.2
|
||||
test_guauge{label="3"} 1.3
|
||||
`
|
||||
type fakeCollector struct {
|
||||
*collector.BaseCollector
|
||||
}
|
||||
|
||||
type fakeRule struct {
|
||||
URLs []string `label:"URLs" json:"urls,required" description:"An array of urls to scrape metrics from" example:"http://my-service-exporter:8080/metrics"`
|
||||
ResponseTimeout int `label:"RESP Timeout" json:"response_timeout" default:"3" description:"Specify timeout duration for slower prometheus clients"`
|
||||
}
|
||||
|
||||
func (p *fakeRule) Validate() error {
|
||||
if len(p.URLs) == 0 || p.URLs[0] == "" {
|
||||
return fmt.Errorf(" prometheus.rule unable to get urls")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *fakeRule) TelegrafInput() (telegraf.Input, error) {
|
||||
if err := p.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
input := &prometheus.Prometheus{
|
||||
URLs: p.URLs,
|
||||
URLTag: "target",
|
||||
MetricVersion: 2,
|
||||
}
|
||||
|
||||
if err := setValue(&input.ResponseTimeout.Duration,
|
||||
time.Second*time.Duration(p.ResponseTimeout)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func setValue(in interface{}, value interface{}) error {
|
||||
rv := reflect.Indirect(reflect.ValueOf(in))
|
||||
|
||||
if !rv.IsValid() || !rv.CanSet() {
|
||||
return fmt.Errorf("invalid argument IsValid %v CanSet %v", rv.IsValid(), rv.CanSet())
|
||||
}
|
||||
rv.Set(reflect.Indirect(reflect.ValueOf(value)))
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue