kill plugin processes when grafana shuts down

This commit is contained in:
bergquist
2017-09-22 16:04:06 +02:00
parent a2d47427ba
commit e1d4bf2607
15 changed files with 619 additions and 246 deletions

View File

@@ -22,7 +22,6 @@ import (
"github.com/grafana/grafana/pkg/metrics"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins"
tsdbplugins "github.com/grafana/grafana/pkg/plugins/backend"
"github.com/grafana/grafana/pkg/services/alerting"
"github.com/grafana/grafana/pkg/services/cleanup"
"github.com/grafana/grafana/pkg/services/notifications"
@@ -67,13 +66,13 @@ func (g *GrafanaServerImpl) Start() {
search.Init()
login.Init()
social.NewOAuthService()
plugins.Init()
pluginClient, err := tsdbplugins.Init()
pluginCloser, err := plugins.Init()
if err != nil {
g.log.Error("failed to start plugins", "error", err)
g.Shutdown(1, "Startup failed")
}
defer pluginClient.Kill()
defer pluginCloser()
if err := provisioning.Init(g.context, setting.HomePath, setting.Cfg); err != nil {
logger.Error("Failed to provision Grafana from config", "error", err)
@@ -81,13 +80,13 @@ func (g *GrafanaServerImpl) Start() {
return
}
closer, err := tracing.Init(setting.Cfg)
tracingCloser, err := tracing.Init(setting.Cfg)
if err != nil {
g.log.Error("Tracing settings is not valid", "error", err)
g.Shutdown(1, "Startup failed")
return
}
defer closer.Close()
defer tracingCloser.Close()
// init alerting
if setting.AlertingEnabled && setting.ExecuteAlerts {

View File

@@ -1,4 +1,4 @@
package plugins
package backend
import (
"log"
@@ -7,32 +7,32 @@ import (
hclog "github.com/hashicorp/go-hclog"
)
type logWrapper struct {
logger glog.Logger
type LogWrapper struct {
Logger glog.Logger
}
func (lw logWrapper) Trace(msg string, args ...interface{}) {}
func (lw logWrapper) Debug(msg string, args ...interface{}) {}
func (lw logWrapper) Info(msg string, args ...interface{}) {}
func (lw logWrapper) Warn(msg string, args ...interface{}) {}
func (lw logWrapper) Error(msg string, args ...interface{}) {}
func (lw LogWrapper) Trace(msg string, args ...interface{}) {}
func (lw LogWrapper) Debug(msg string, args ...interface{}) {}
func (lw LogWrapper) Info(msg string, args ...interface{}) {}
func (lw LogWrapper) Warn(msg string, args ...interface{}) {}
func (lw LogWrapper) Error(msg string, args ...interface{}) {}
func (lw logWrapper) IsTrace() bool { return true }
func (lw logWrapper) IsDebug() bool { return true }
func (lw logWrapper) IsInfo() bool { return true }
func (lw logWrapper) IsWarn() bool { return true }
func (lw logWrapper) IsError() bool { return true }
func (lw LogWrapper) IsTrace() bool { return true }
func (lw LogWrapper) IsDebug() bool { return true }
func (lw LogWrapper) IsInfo() bool { return true }
func (lw LogWrapper) IsWarn() bool { return true }
func (lw LogWrapper) IsError() bool { return true }
func (lw logWrapper) With(args ...interface{}) hclog.Logger {
return logWrapper{logger: glog.New("logger", args)}
func (lw LogWrapper) With(args ...interface{}) hclog.Logger {
return LogWrapper{Logger: glog.New("logger", args)}
}
func (lw logWrapper) Named(name string) hclog.Logger {
return logWrapper{logger: glog.New(name)}
func (lw LogWrapper) Named(name string) hclog.Logger {
return LogWrapper{Logger: glog.New(name)}
}
func (lw logWrapper) ResetNamed(name string) hclog.Logger {
return logWrapper{logger: glog.New(name)}
func (lw LogWrapper) ResetNamed(name string) hclog.Logger {
return LogWrapper{Logger: glog.New(name)}
}
func (lw logWrapper) StandardLogger(ops *hclog.StandardLoggerOptions) *log.Logger {
func (lw LogWrapper) StandardLogger(ops *hclog.StandardLoggerOptions) *log.Logger {
return nil
}

View File

@@ -1,4 +0,0 @@
all: build
build:
go build -o simple-plugin .

View File

@@ -1,39 +0,0 @@
package main
import (
"golang.org/x/net/context"
"log"
shared "github.com/grafana/grafana/pkg/plugins/backend/shared"
proto "github.com/grafana/grafana/pkg/tsdb/models"
plugin "github.com/hashicorp/go-plugin"
)
type Tsdb struct {
plugin.NetRPCUnsupportedPlugin
}
func (Tsdb) Get(ctx context.Context, req *proto.TsdbRequest) (*proto.TsdbResponse, error) {
log.Print("Tsdb.Get() from plugin")
return &proto.TsdbResponse{
MetaJson: "from plugins! meta meta",
}, nil
}
func main() {
plugin.Serve(&plugin.ServeConfig{
HandshakeConfig: plugin.HandshakeConfig{
ProtocolVersion: 1,
MagicCookieKey: "BASIC_PLUGIN",
MagicCookieValue: "hello",
},
Plugins: map[string]plugin.Plugin{
"tsdb_mock": &shared.TsdbPluginImpl{Plugin: &Tsdb{}},
},
// A non-nil value here enables gRPC serving for this plugin...
GRPCServer: plugin.DefaultGRPCServer,
})
}

View File

@@ -1,55 +0,0 @@
package plugins
import (
"os/exec"
"golang.org/x/net/context"
"github.com/grafana/grafana/pkg/log"
"github.com/grafana/grafana/pkg/plugins/backend/shared"
"github.com/grafana/grafana/pkg/tsdb/models"
plugin "github.com/hashicorp/go-plugin"
)
func Init() (*plugin.Client, error) {
/*
setup protoc using https://gist.github.com/bergquist/5df1f201bb605e42538ef40f6ccf82a9
run "protoc --go_out=plugins=grpc:. *.proto" to update proto files
*/
logger := log.New("grafana.plugins")
client := plugin.NewClient(&plugin.ClientConfig{
HandshakeConfig: plugin.HandshakeConfig{
ProtocolVersion: 1,
MagicCookieKey: "BASIC_PLUGIN",
MagicCookieValue: "hello",
},
Plugins: shared.PluginMap,
Cmd: exec.Command("sh", "-c", "/home/carl/go/src/github.com/grafana/grafana/pkg/plugins/backend/mock_tsdb_plugin/simple-plugin"),
AllowedProtocols: []plugin.Protocol{plugin.ProtocolGRPC},
Logger: logWrapper{logger: logger},
})
// Connect via RPC
rpcClient, err := client.Client()
if err != nil {
return nil, err
}
// Request the plugin
raw, err := rpcClient.Dispense("tsdb_mock")
if err != nil {
return nil, err
}
plugin := raw.(shared.TsdbPlugin)
response, err := plugin.Get(context.Background(), &proto.TsdbRequest{})
if err != nil {
logger.Error("Response from plugin. ", "response", response)
} else {
logger.Info("Response from plugin. ", "response", response)
}
return client, nil
}

View File

@@ -1,22 +0,0 @@
package shared
import (
proto "github.com/grafana/grafana/pkg/tsdb/models"
"golang.org/x/net/context"
)
type GRPCClient struct {
proto.TsdbPluginClient
}
func (m *GRPCClient) Get(ctx context.Context, req *proto.TsdbRequest) (*proto.TsdbResponse, error) {
return m.TsdbPluginClient.Get(ctx, req)
}
type GRPCServer struct {
TsdbPlugin
}
func (m *GRPCServer) Get(ctx context.Context, req *proto.TsdbRequest) (*proto.TsdbResponse, error) {
return m.TsdbPlugin.Get(ctx, req)
}

View File

@@ -0,0 +1,90 @@
package plugins
import (
"context"
"encoding/json"
"os/exec"
"path"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins/backend"
"github.com/grafana/grafana/pkg/tsdb"
"github.com/grafana/grafana/pkg/log"
proto "github.com/grafana/grafana/pkg/tsdb/models"
shared "github.com/grafana/grafana/pkg/tsdb/models/proxy"
plugin "github.com/hashicorp/go-plugin"
)
type BackendDatasource struct {
*PluginBase
Executable string
client *plugin.Client
}
type Killable interface {
Kill()
}
type NoopKiller struct{}
func (nk NoopKiller) Kill() {}
func (p *BackendDatasource) initBackendPlugin() (Killable, error) {
logger := log.New("grafana.plugins")
p.client = plugin.NewClient(&plugin.ClientConfig{
HandshakeConfig: plugin.HandshakeConfig{
ProtocolVersion: 1,
MagicCookieKey: "BASIC_PLUGIN",
MagicCookieValue: "hello",
},
Plugins: map[string]plugin.Plugin{p.Id: &shared.TsdbPluginImpl{}},
Cmd: exec.Command("sh", "-c", path.Join(p.PluginDir, p.Executable)),
AllowedProtocols: []plugin.Protocol{plugin.ProtocolGRPC},
Logger: backend.LogWrapper{Logger: logger},
})
rpcClient, err := p.client.Client()
if err != nil {
return NoopKiller{}, err
}
raw, err := rpcClient.Dispense(p.Id)
if err != nil {
return NoopKiller{}, err
}
plugin := raw.(shared.TsdbPlugin)
response, err := plugin.Query(context.Background(), &proto.TsdbQuery{})
if err != nil {
logger.Error("Response from plugin. ", "response", response)
} else {
logger.Info("Response from plugin. ", "response", response)
}
tsdb.RegisterTsdbQueryEndpoint(p.Id, func(dsInfo *models.DataSource) (tsdb.TsdbQueryEndpoint, error) {
return &shared.TsdbWrapper{TsdbPlugin: plugin}, nil
})
return p.client, nil
}
func (p *BackendDatasource) Kill() {
p.client.Kill()
}
func (p *BackendDatasource) Load(decoder *json.Decoder, pluginDir string) error {
if err := decoder.Decode(&p); err != nil {
return err
}
if err := p.registerPlugin(pluginDir); err != nil {
return err
}
BackendDatasources[p.Id] = p
return nil
}

View File

@@ -17,12 +17,13 @@ import (
)
var (
DataSources map[string]*DataSourcePlugin
Panels map[string]*PanelPlugin
StaticRoutes []*PluginStaticRoute
Apps map[string]*AppPlugin
Plugins map[string]*PluginBase
PluginTypes map[string]interface{}
DataSources map[string]*DataSourcePlugin
Panels map[string]*PanelPlugin
StaticRoutes []*PluginStaticRoute
Apps map[string]*AppPlugin
Plugins map[string]*PluginBase
BackendDatasources map[string]*BackendDatasource
PluginTypes map[string]interface{}
GrafanaLatestVersion string
GrafanaHasUpdate bool
@@ -34,7 +35,9 @@ type PluginScanner struct {
errors []error
}
func Init() error {
type Dispose func()
func Init() (Dispose, error) {
plog = log.New("plugins")
DataSources = make(map[string]*DataSourcePlugin)
@@ -42,10 +45,12 @@ func Init() error {
Panels = make(map[string]*PanelPlugin)
Apps = make(map[string]*AppPlugin)
Plugins = make(map[string]*PluginBase)
BackendDatasources = make(map[string]*BackendDatasource)
PluginTypes = map[string]interface{}{
"panel": PanelPlugin{},
"datasource": DataSourcePlugin{},
"app": AppPlugin{},
"panel": PanelPlugin{},
"datasource": DataSourcePlugin{},
"app": AppPlugin{},
"backend-datasource": BackendDatasource{},
}
plog.Info("Starting plugin search")
@@ -77,10 +82,26 @@ func Init() error {
app.initApp()
}
killers := []Killable{}
for _, be := range BackendDatasources {
killable, err := be.initBackendPlugin()
if err != nil {
plog.Error("failed to init plugin", "id", be.Id, "error", err)
} else {
killers = append(killers, killable)
}
}
go StartPluginUpdateChecker()
go updateAppDashboards()
return nil
return dispose, nil
}
func dispose() {
for _, p := range BackendDatasources {
p.Kill()
}
}
func checkPluginPaths() error {

View File

@@ -14,9 +14,7 @@ type TsdbQuery struct {
type Query struct {
RefId string
Model *simplejson.Json
Depends []string
DataSource *models.DataSource
Results []*TimeSeries
MaxDataPoints int64
IntervalMs int64
}

View File

@@ -0,0 +1,24 @@
package proxy
import (
proto "github.com/grafana/grafana/pkg/tsdb/models"
"golang.org/x/net/context"
)
type GRPCClient struct {
proto.TsdbPluginClient
}
//Query(ctx context.Context, ds *models.DataSource, query *TsdbQuery) (*Response, error)
func (m *GRPCClient) Query(ctx context.Context, req *proto.TsdbQuery) (*proto.Response, error) {
return m.TsdbPluginClient.Query(ctx, req)
}
type GRPCServer struct {
TsdbPlugin
}
func (m *GRPCServer) Query(ctx context.Context, req *proto.TsdbQuery) (*proto.Response, error) {
return m.TsdbPlugin.Query(ctx, req)
}

View File

@@ -1,8 +1,10 @@
package shared
package proxy
import (
"golang.org/x/net/context"
//tsdb "github.com/grafana/grafana/pkg/tsdb"
proto "github.com/grafana/grafana/pkg/tsdb/models"
plugin "github.com/hashicorp/go-plugin"
"google.golang.org/grpc"
@@ -13,7 +15,7 @@ var PluginMap = map[string]plugin.Plugin{
}
type TsdbPlugin interface {
Get(ctx context.Context, req *proto.TsdbRequest) (*proto.TsdbResponse, error)
Query(ctx context.Context, req *proto.TsdbQuery) (*proto.Response, error)
}
type TsdbPluginImpl struct { //LOL IMPL LOL

View File

@@ -0,0 +1,83 @@
package proxy
import (
"github.com/golang/protobuf/ptypes"
"github.com/grafana/grafana/pkg/components/null"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/tsdb"
proto "github.com/grafana/grafana/pkg/tsdb/models"
"golang.org/x/net/context"
)
type TsdbWrapper struct {
TsdbPlugin
}
func (tw *TsdbWrapper) Query(ctx context.Context, ds *models.DataSource, query *tsdb.TsdbQuery) (*tsdb.Response, error) {
jsonData, _ := ds.JsonData.MarshalJSON()
now, _ := ptypes.TimestampProto(query.TimeRange.Now)
pbQuery := &proto.TsdbQuery{
Datasource: &proto.DatasourceInfo{
Access: string(ds.Access),
BasicAuth: ds.BasicAuth,
BasicAuthUser: ds.BasicAuthUser,
BasicAuthPassword: ds.BasicAuthPassword,
JsonData: string(jsonData),
Name: ds.Name,
Type: ds.Type,
Url: ds.Url,
},
Timerange: &proto.Timerange{
From: query.TimeRange.From,
To: query.TimeRange.To,
Now: now,
},
Queries: []*proto.Query{},
}
for _, q := range query.Queries {
modelJson, _ := q.Model.MarshalJSON()
pbQuery.Queries = append(pbQuery.Queries, &proto.Query{
ModelJson: string(modelJson),
IntervalMs: q.IntervalMs,
RefId: q.RefId,
MaxDataPoints: q.MaxDataPoints,
})
}
pbres, err := tw.TsdbPlugin.Query(ctx, pbQuery)
if err != nil {
return nil, err
}
res := &tsdb.Response{
Message: pbres.Message,
}
for _, r := range pbres.Results {
res.Results[r.RefId] = &tsdb.QueryResult{
RefId: r.RefId,
Series: []*tsdb.TimeSeries{},
}
for _, s := range r.Series {
points := tsdb.TimeSeriesPoints{}
for _, p := range s.Points {
po := tsdb.NewTimePoint(null.FloatFrom(float64(p.Timestamp.Nanos)), p.Value)
points = append(points, po)
}
res.Results[r.RefId].Series = append(res.Results[r.RefId].Series, &tsdb.TimeSeries{
Name: s.Name,
Tags: s.Tags,
Points: points,
})
}
}
return res, nil
}

View File

@@ -8,16 +8,21 @@ It is generated from these files:
tsdb_plugin.proto
It has these top-level messages:
TsdbRequest
TsdbQuery
TsdbResponse
Query
Timerange
Response
QueryResult
DatasourceInfo
TsdbSeries
Point
*/
package proto
import proto1 "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import google_protobuf "github.com/golang/protobuf/ptypes/timestamp"
import (
context "golang.org/x/net/context"
@@ -36,55 +41,143 @@ var _ = math.Inf
const _ = proto1.ProtoPackageIsVersion2 // please upgrade the proto package
// Message represents a simple message sent to the Echo service.
type TsdbRequest struct {
From int64 `protobuf:"varint,1,opt,name=from" json:"from,omitempty"`
To int64 `protobuf:"varint,2,opt,name=to" json:"to,omitempty"`
Queries []*TsdbQuery `protobuf:"bytes,3,rep,name=queries" json:"queries,omitempty"`
type TsdbQuery struct {
Timerange *Timerange `protobuf:"bytes,1,opt,name=timerange" json:"timerange,omitempty"`
Datasource *DatasourceInfo `protobuf:"bytes,2,opt,name=datasource" json:"datasource,omitempty"`
Queries []*Query `protobuf:"bytes,3,rep,name=queries" json:"queries,omitempty"`
}
func (m *TsdbRequest) Reset() { *m = TsdbRequest{} }
func (m *TsdbRequest) String() string { return proto1.CompactTextString(m) }
func (*TsdbRequest) ProtoMessage() {}
func (*TsdbRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
func (m *TsdbQuery) Reset() { *m = TsdbQuery{} }
func (m *TsdbQuery) String() string { return proto1.CompactTextString(m) }
func (*TsdbQuery) ProtoMessage() {}
func (*TsdbQuery) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
func (m *TsdbRequest) GetFrom() int64 {
func (m *TsdbQuery) GetTimerange() *Timerange {
if m != nil {
return m.From
return m.Timerange
}
return 0
return nil
}
func (m *TsdbRequest) GetTo() int64 {
func (m *TsdbQuery) GetDatasource() *DatasourceInfo {
if m != nil {
return m.To
return m.Datasource
}
return 0
return nil
}
func (m *TsdbRequest) GetQueries() []*TsdbQuery {
func (m *TsdbQuery) GetQueries() []*Query {
if m != nil {
return m.Queries
}
return nil
}
type TsdbQuery struct {
QueryJson string `protobuf:"bytes,1,opt,name=queryJson" json:"queryJson,omitempty"`
type Query struct {
RefId string `protobuf:"bytes,1,opt,name=refId" json:"refId,omitempty"`
ModelJson string `protobuf:"bytes,2,opt,name=modelJson" json:"modelJson,omitempty"`
MaxDataPoints int64 `protobuf:"varint,3,opt,name=MaxDataPoints" json:"MaxDataPoints,omitempty"`
IntervalMs int64 `protobuf:"varint,4,opt,name=intervalMs" json:"intervalMs,omitempty"`
Datasource *DatasourceInfo `protobuf:"bytes,5,opt,name=datasource" json:"datasource,omitempty"`
}
func (m *TsdbQuery) Reset() { *m = TsdbQuery{} }
func (m *TsdbQuery) String() string { return proto1.CompactTextString(m) }
func (*TsdbQuery) ProtoMessage() {}
func (*TsdbQuery) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
func (m *Query) Reset() { *m = Query{} }
func (m *Query) String() string { return proto1.CompactTextString(m) }
func (*Query) ProtoMessage() {}
func (*Query) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
func (m *TsdbQuery) GetQueryJson() string {
func (m *Query) GetRefId() string {
if m != nil {
return m.QueryJson
return m.RefId
}
return ""
}
type TsdbResponse struct {
func (m *Query) GetModelJson() string {
if m != nil {
return m.ModelJson
}
return ""
}
func (m *Query) GetMaxDataPoints() int64 {
if m != nil {
return m.MaxDataPoints
}
return 0
}
func (m *Query) GetIntervalMs() int64 {
if m != nil {
return m.IntervalMs
}
return 0
}
func (m *Query) GetDatasource() *DatasourceInfo {
if m != nil {
return m.Datasource
}
return nil
}
type Timerange struct {
From string `protobuf:"bytes,1,opt,name=from" json:"from,omitempty"`
To string `protobuf:"bytes,2,opt,name=to" json:"to,omitempty"`
Now *google_protobuf.Timestamp `protobuf:"bytes,3,opt,name=now" json:"now,omitempty"`
}
func (m *Timerange) Reset() { *m = Timerange{} }
func (m *Timerange) String() string { return proto1.CompactTextString(m) }
func (*Timerange) ProtoMessage() {}
func (*Timerange) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
func (m *Timerange) GetFrom() string {
if m != nil {
return m.From
}
return ""
}
func (m *Timerange) GetTo() string {
if m != nil {
return m.To
}
return ""
}
func (m *Timerange) GetNow() *google_protobuf.Timestamp {
if m != nil {
return m.Now
}
return nil
}
type Response struct {
Message string `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"`
Results []*QueryResult `protobuf:"bytes,2,rep,name=results" json:"results,omitempty"`
}
func (m *Response) Reset() { *m = Response{} }
func (m *Response) String() string { return proto1.CompactTextString(m) }
func (*Response) ProtoMessage() {}
func (*Response) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
func (m *Response) GetMessage() string {
if m != nil {
return m.Message
}
return ""
}
func (m *Response) GetResults() []*QueryResult {
if m != nil {
return m.Results
}
return nil
}
type QueryResult struct {
Error string `protobuf:"bytes,1,opt,name=error" json:"error,omitempty"`
ErrorString string `protobuf:"bytes,2,opt,name=errorString" json:"errorString,omitempty"`
RefId string `protobuf:"bytes,3,opt,name=refId" json:"refId,omitempty"`
@@ -92,54 +185,136 @@ type TsdbResponse struct {
Series []*TsdbSeries `protobuf:"bytes,5,rep,name=series" json:"series,omitempty"`
}
func (m *TsdbResponse) Reset() { *m = TsdbResponse{} }
func (m *TsdbResponse) String() string { return proto1.CompactTextString(m) }
func (*TsdbResponse) ProtoMessage() {}
func (*TsdbResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
func (m *QueryResult) Reset() { *m = QueryResult{} }
func (m *QueryResult) String() string { return proto1.CompactTextString(m) }
func (*QueryResult) ProtoMessage() {}
func (*QueryResult) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
func (m *TsdbResponse) GetError() string {
func (m *QueryResult) GetError() string {
if m != nil {
return m.Error
}
return ""
}
func (m *TsdbResponse) GetErrorString() string {
func (m *QueryResult) GetErrorString() string {
if m != nil {
return m.ErrorString
}
return ""
}
func (m *TsdbResponse) GetRefId() string {
func (m *QueryResult) GetRefId() string {
if m != nil {
return m.RefId
}
return ""
}
func (m *TsdbResponse) GetMetaJson() string {
func (m *QueryResult) GetMetaJson() string {
if m != nil {
return m.MetaJson
}
return ""
}
func (m *TsdbResponse) GetSeries() []*TsdbSeries {
func (m *QueryResult) GetSeries() []*TsdbSeries {
if m != nil {
return m.Series
}
return nil
}
type DatasourceInfo struct {
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
Type string `protobuf:"bytes,2,opt,name=type" json:"type,omitempty"`
Access string `protobuf:"bytes,3,opt,name=access" json:"access,omitempty"`
Url string `protobuf:"bytes,4,opt,name=url" json:"url,omitempty"`
BasicAuth bool `protobuf:"varint,5,opt,name=basicAuth" json:"basicAuth,omitempty"`
BasicAuthUser string `protobuf:"bytes,6,opt,name=basicAuthUser" json:"basicAuthUser,omitempty"`
BasicAuthPassword string `protobuf:"bytes,7,opt,name=basicAuthPassword" json:"basicAuthPassword,omitempty"`
JsonData string `protobuf:"bytes,8,opt,name=jsonData" json:"jsonData,omitempty"`
SecureJsonData string `protobuf:"bytes,9,opt,name=secureJsonData" json:"secureJsonData,omitempty"`
}
func (m *DatasourceInfo) Reset() { *m = DatasourceInfo{} }
func (m *DatasourceInfo) String() string { return proto1.CompactTextString(m) }
func (*DatasourceInfo) ProtoMessage() {}
func (*DatasourceInfo) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
func (m *DatasourceInfo) GetName() string {
if m != nil {
return m.Name
}
return ""
}
func (m *DatasourceInfo) GetType() string {
if m != nil {
return m.Type
}
return ""
}
func (m *DatasourceInfo) GetAccess() string {
if m != nil {
return m.Access
}
return ""
}
func (m *DatasourceInfo) GetUrl() string {
if m != nil {
return m.Url
}
return ""
}
func (m *DatasourceInfo) GetBasicAuth() bool {
if m != nil {
return m.BasicAuth
}
return false
}
func (m *DatasourceInfo) GetBasicAuthUser() string {
if m != nil {
return m.BasicAuthUser
}
return ""
}
func (m *DatasourceInfo) GetBasicAuthPassword() string {
if m != nil {
return m.BasicAuthPassword
}
return ""
}
func (m *DatasourceInfo) GetJsonData() string {
if m != nil {
return m.JsonData
}
return ""
}
func (m *DatasourceInfo) GetSecureJsonData() string {
if m != nil {
return m.SecureJsonData
}
return ""
}
type TsdbSeries struct {
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
Tags map[string]string `protobuf:"bytes,2,rep,name=tags" json:"tags,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
Points []*Point `protobuf:"bytes,3,rep,name=points" json:"points,omitempty"`
}
func (m *TsdbSeries) Reset() { *m = TsdbSeries{} }
func (m *TsdbSeries) String() string { return proto1.CompactTextString(m) }
func (*TsdbSeries) ProtoMessage() {}
func (*TsdbSeries) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
func (*TsdbSeries) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
func (m *TsdbSeries) GetName() string {
if m != nil {
@@ -148,11 +323,53 @@ func (m *TsdbSeries) GetName() string {
return ""
}
func (m *TsdbSeries) GetTags() map[string]string {
if m != nil {
return m.Tags
}
return nil
}
func (m *TsdbSeries) GetPoints() []*Point {
if m != nil {
return m.Points
}
return nil
}
type Point struct {
Timestamp *google_protobuf.Timestamp `protobuf:"bytes,1,opt,name=timestamp" json:"timestamp,omitempty"`
Value float64 `protobuf:"fixed64,2,opt,name=value" json:"value,omitempty"`
}
func (m *Point) Reset() { *m = Point{} }
func (m *Point) String() string { return proto1.CompactTextString(m) }
func (*Point) ProtoMessage() {}
func (*Point) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
func (m *Point) GetTimestamp() *google_protobuf.Timestamp {
if m != nil {
return m.Timestamp
}
return nil
}
func (m *Point) GetValue() float64 {
if m != nil {
return m.Value
}
return 0
}
func init() {
proto1.RegisterType((*TsdbRequest)(nil), "plugins.TsdbRequest")
proto1.RegisterType((*TsdbQuery)(nil), "plugins.TsdbQuery")
proto1.RegisterType((*TsdbResponse)(nil), "plugins.TsdbResponse")
proto1.RegisterType((*Query)(nil), "plugins.Query")
proto1.RegisterType((*Timerange)(nil), "plugins.Timerange")
proto1.RegisterType((*Response)(nil), "plugins.Response")
proto1.RegisterType((*QueryResult)(nil), "plugins.QueryResult")
proto1.RegisterType((*DatasourceInfo)(nil), "plugins.DatasourceInfo")
proto1.RegisterType((*TsdbSeries)(nil), "plugins.TsdbSeries")
proto1.RegisterType((*Point)(nil), "plugins.Point")
}
// Reference imports to suppress errors if they are not otherwise used.
@@ -166,7 +383,7 @@ const _ = grpc.SupportPackageIsVersion4
// Client API for TsdbPlugin service
type TsdbPluginClient interface {
Get(ctx context.Context, in *TsdbRequest, opts ...grpc.CallOption) (*TsdbResponse, error)
Query(ctx context.Context, in *TsdbQuery, opts ...grpc.CallOption) (*Response, error)
}
type tsdbPluginClient struct {
@@ -177,9 +394,9 @@ func NewTsdbPluginClient(cc *grpc.ClientConn) TsdbPluginClient {
return &tsdbPluginClient{cc}
}
func (c *tsdbPluginClient) Get(ctx context.Context, in *TsdbRequest, opts ...grpc.CallOption) (*TsdbResponse, error) {
out := new(TsdbResponse)
err := grpc.Invoke(ctx, "/plugins.TsdbPlugin/Get", in, out, c.cc, opts...)
func (c *tsdbPluginClient) Query(ctx context.Context, in *TsdbQuery, opts ...grpc.CallOption) (*Response, error) {
out := new(Response)
err := grpc.Invoke(ctx, "/plugins.TsdbPlugin/Query", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
@@ -189,27 +406,27 @@ func (c *tsdbPluginClient) Get(ctx context.Context, in *TsdbRequest, opts ...grp
// Server API for TsdbPlugin service
type TsdbPluginServer interface {
Get(context.Context, *TsdbRequest) (*TsdbResponse, error)
Query(context.Context, *TsdbQuery) (*Response, error)
}
func RegisterTsdbPluginServer(s *grpc.Server, srv TsdbPluginServer) {
s.RegisterService(&_TsdbPlugin_serviceDesc, srv)
}
func _TsdbPlugin_Get_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(TsdbRequest)
func _TsdbPlugin_Query_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(TsdbQuery)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TsdbPluginServer).Get(ctx, in)
return srv.(TsdbPluginServer).Query(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/plugins.TsdbPlugin/Get",
FullMethod: "/plugins.TsdbPlugin/Query",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TsdbPluginServer).Get(ctx, req.(*TsdbRequest))
return srv.(TsdbPluginServer).Query(ctx, req.(*TsdbQuery))
}
return interceptor(ctx, in, info, handler)
}
@@ -219,8 +436,8 @@ var _TsdbPlugin_serviceDesc = grpc.ServiceDesc{
HandlerType: (*TsdbPluginServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Get",
Handler: _TsdbPlugin_Get_Handler,
MethodName: "Query",
Handler: _TsdbPlugin_Query_Handler,
},
},
Streams: []grpc.StreamDesc{},
@@ -230,23 +447,46 @@ var _TsdbPlugin_serviceDesc = grpc.ServiceDesc{
func init() { proto1.RegisterFile("tsdb_plugin.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 280 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0x51, 0xc1, 0x4e, 0x83, 0x40,
0x10, 0x0d, 0x50, 0x8a, 0x0c, 0xc6, 0xc4, 0xb1, 0x26, 0xa4, 0xf1, 0x40, 0x38, 0xd5, 0x68, 0x38,
0xe0, 0x0f, 0x18, 0x2f, 0x46, 0x4f, 0xba, 0xf5, 0xe4, 0xa5, 0x29, 0x61, 0xda, 0x90, 0x08, 0x4b,
0x77, 0x97, 0x43, 0x3f, 0xc8, 0xff, 0x34, 0xcc, 0xae, 0xad, 0xf5, 0xc4, 0xbc, 0xb7, 0x6f, 0xde,
0xcc, 0x1b, 0xe0, 0xd2, 0xe8, 0xba, 0x5a, 0xf5, 0x5f, 0xc3, 0xb6, 0xe9, 0x8a, 0x5e, 0x49, 0x23,
0x31, 0xb2, 0x48, 0xe7, 0x2b, 0x48, 0x3e, 0x74, 0x5d, 0x09, 0xda, 0x0d, 0xa4, 0x0d, 0x22, 0x4c,
0x36, 0x4a, 0xb6, 0xa9, 0x97, 0x79, 0x8b, 0x40, 0x70, 0x8d, 0x17, 0xe0, 0x1b, 0x99, 0xfa, 0xcc,
0xf8, 0x46, 0xe2, 0x3d, 0x44, 0xbb, 0x81, 0x54, 0x43, 0x3a, 0x0d, 0xb2, 0x60, 0x91, 0x94, 0x58,
0x38, 0xb7, 0x62, 0xb4, 0x7a, 0x1f, 0x48, 0xed, 0xc5, 0xaf, 0x24, 0xbf, 0x85, 0xf8, 0xc0, 0xe2,
0x0d, 0xc4, 0x23, 0xbf, 0x7f, 0xd5, 0xb2, 0xe3, 0x19, 0xb1, 0x38, 0x12, 0xf9, 0xb7, 0x07, 0xe7,
0x76, 0x19, 0xdd, 0xcb, 0x4e, 0x13, 0xce, 0x20, 0x24, 0xa5, 0xa4, 0x72, 0x52, 0x0b, 0x30, 0x83,
0x84, 0x8b, 0xa5, 0x51, 0x4d, 0xb7, 0xe5, 0xc5, 0x62, 0xf1, 0x97, 0x1a, 0xfb, 0x14, 0x6d, 0x5e,
0xea, 0x34, 0xb0, 0x7d, 0x0c, 0x70, 0x0e, 0x67, 0x2d, 0x99, 0x35, 0xcf, 0x9e, 0xf0, 0xc3, 0x01,
0xe3, 0x1d, 0x4c, 0xb5, 0x8d, 0x14, 0x72, 0xa4, 0xab, 0x93, 0x48, 0x4b, 0x7e, 0x12, 0x4e, 0x92,
0x67, 0x00, 0x47, 0x76, 0x3c, 0x59, 0xb7, 0x6e, 0xc9, 0xed, 0xc8, 0x75, 0xf9, 0x68, 0x15, 0x6f,
0xec, 0x81, 0x25, 0x04, 0xcf, 0x64, 0x70, 0x76, 0xe2, 0xe9, 0x2e, 0x3e, 0xbf, 0xfe, 0xc7, 0xda,
0xe8, 0x4f, 0xd1, 0x67, 0xc8, 0x7f, 0xaa, 0x9a, 0xf2, 0xe7, 0xe1, 0x27, 0x00, 0x00, 0xff, 0xff,
0x11, 0xda, 0x61, 0xe4, 0xc5, 0x01, 0x00, 0x00,
// 652 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x54, 0x4d, 0x6f, 0xd4, 0x3a,
0x14, 0x55, 0xe6, 0x3b, 0x77, 0xf4, 0x46, 0xaf, 0x7e, 0xd5, 0x23, 0x1a, 0xf1, 0x51, 0x45, 0xa8,
0x1a, 0x89, 0x2a, 0x85, 0x61, 0xd1, 0x0a, 0xb1, 0x01, 0xc1, 0xa2, 0x95, 0x2a, 0x15, 0x77, 0x10,
0x12, 0x12, 0x42, 0x9e, 0x89, 0x27, 0x04, 0x92, 0x78, 0xb0, 0x9d, 0x96, 0xf9, 0x27, 0x2c, 0x59,
0xf0, 0x13, 0x58, 0xf1, 0xeb, 0x90, 0x6f, 0xec, 0x64, 0xa6, 0x54, 0x88, 0x55, 0xee, 0x3d, 0xf7,
0xd8, 0x39, 0x3e, 0xf7, 0xda, 0xb0, 0xa3, 0x55, 0x3c, 0x7f, 0xbf, 0xca, 0xca, 0x24, 0x2d, 0xa2,
0x95, 0x14, 0x5a, 0x90, 0x7e, 0x95, 0xa9, 0xf1, 0xbd, 0x44, 0x88, 0x24, 0xe3, 0x87, 0x08, 0xcf,
0xcb, 0xe5, 0xa1, 0x4e, 0x73, 0xae, 0x34, 0xcb, 0x57, 0x15, 0x33, 0xfc, 0xe6, 0x81, 0x3f, 0x53,
0xf1, 0xfc, 0x55, 0xc9, 0xe5, 0x9a, 0x3c, 0x04, 0xdf, 0x10, 0x24, 0x2b, 0x12, 0x1e, 0x78, 0x7b,
0xde, 0x64, 0x38, 0x25, 0x91, 0xdd, 0x2b, 0x9a, 0xb9, 0x0a, 0x6d, 0x48, 0xe4, 0x08, 0x20, 0x66,
0x9a, 0x29, 0x51, 0xca, 0x05, 0x0f, 0x5a, 0xb8, 0xe4, 0x56, 0xbd, 0xe4, 0x45, 0x5d, 0x3a, 0x29,
0x96, 0x82, 0x6e, 0x50, 0xc9, 0x04, 0xfa, 0x9f, 0x4b, 0x2e, 0x53, 0xae, 0x82, 0xf6, 0x5e, 0x7b,
0x32, 0x9c, 0x8e, 0xea, 0x55, 0xa8, 0x85, 0xba, 0x72, 0xf8, 0xd3, 0x83, 0x6e, 0x25, 0x6f, 0x17,
0xba, 0x92, 0x2f, 0x4f, 0x62, 0x94, 0xe6, 0xd3, 0x2a, 0x21, 0xb7, 0xc1, 0xcf, 0x45, 0xcc, 0xb3,
0x53, 0x25, 0x0a, 0x54, 0xe0, 0xd3, 0x06, 0x20, 0xf7, 0xe1, 0x9f, 0x33, 0xf6, 0xc5, 0x08, 0x39,
0x17, 0x69, 0xa1, 0xcd, 0xdf, 0xbc, 0x49, 0x9b, 0x6e, 0x83, 0xe4, 0x2e, 0x40, 0x5a, 0x68, 0x2e,
0x2f, 0x59, 0x76, 0xa6, 0x82, 0x0e, 0x52, 0x36, 0x90, 0x6b, 0xc7, 0xec, 0xfe, 0xf5, 0x31, 0xc3,
0x77, 0xe0, 0xd7, 0xbe, 0x11, 0x02, 0x9d, 0xa5, 0x14, 0xb9, 0x95, 0x8f, 0x31, 0x19, 0x41, 0x4b,
0x0b, 0x2b, 0xbb, 0xa5, 0x05, 0x39, 0x80, 0x76, 0x21, 0xae, 0x50, 0xe5, 0x70, 0x3a, 0x8e, 0xaa,
0xfe, 0x45, 0xae, 0x7f, 0xd8, 0x04, 0xec, 0x1f, 0x35, 0xb4, 0x70, 0x06, 0x03, 0xca, 0xd5, 0x4a,
0x14, 0x8a, 0x93, 0x00, 0xfa, 0x39, 0x57, 0x8a, 0xd9, 0xd6, 0xf9, 0xd4, 0xa5, 0x24, 0x82, 0xbe,
0xe4, 0xaa, 0xcc, 0xb4, 0x0a, 0x5a, 0xe8, 0xf5, 0xee, 0x35, 0xaf, 0xb1, 0x48, 0x1d, 0x29, 0xfc,
0xee, 0xc1, 0x70, 0xa3, 0x60, 0x7c, 0xe7, 0x52, 0x0a, 0xe9, 0x7c, 0xc7, 0x84, 0xec, 0xc1, 0x10,
0x83, 0x0b, 0x2d, 0xd3, 0x22, 0xb1, 0x47, 0xd8, 0x84, 0x9a, 0x7e, 0xb5, 0x37, 0xfb, 0x35, 0x86,
0x41, 0xce, 0x35, 0xc3, 0x76, 0x75, 0xb0, 0x50, 0xe7, 0xe4, 0x01, 0xf4, 0x54, 0x35, 0x14, 0x5d,
0x14, 0xfa, 0x5f, 0x33, 0x7d, 0x2a, 0x9e, 0x5f, 0x60, 0x89, 0x5a, 0x4a, 0xf8, 0xb5, 0x05, 0xa3,
0x6d, 0xeb, 0x8d, 0xc3, 0x05, 0xcb, 0x9d, 0x01, 0x18, 0x1b, 0x4c, 0xaf, 0x57, 0xdc, 0x0a, 0xc4,
0x98, 0xfc, 0x0f, 0x3d, 0xb6, 0x58, 0x70, 0xa5, 0xac, 0x34, 0x9b, 0x91, 0x7f, 0xa1, 0x5d, 0xca,
0xcc, 0xca, 0x32, 0xa1, 0x99, 0xae, 0x39, 0x53, 0xe9, 0xe2, 0x59, 0xa9, 0x3f, 0x60, 0xe3, 0x07,
0xb4, 0x01, 0xcc, 0x74, 0xd5, 0xc9, 0x6b, 0xc5, 0x65, 0xd0, 0xc3, 0x95, 0xdb, 0x20, 0x39, 0x80,
0x9d, 0x1a, 0x38, 0x67, 0x4a, 0x5d, 0x09, 0x19, 0x07, 0x7d, 0x64, 0xfe, 0x5e, 0x30, 0xfe, 0x7c,
0x54, 0xa2, 0x30, 0x27, 0x0b, 0x06, 0x95, 0x3f, 0x2e, 0x27, 0xfb, 0x30, 0x52, 0x7c, 0x51, 0x4a,
0x7e, 0xea, 0x18, 0x3e, 0x32, 0xae, 0xa1, 0xe1, 0x0f, 0x0f, 0xa0, 0x71, 0xec, 0x46, 0x5b, 0x1e,
0x41, 0x47, 0xb3, 0xc4, 0x4d, 0xc4, 0x9d, 0x1b, 0x8c, 0x8e, 0x66, 0x2c, 0x51, 0x2f, 0x0b, 0x2d,
0xd7, 0x14, 0xa9, 0x64, 0x1f, 0x7a, 0x2b, 0x77, 0x89, 0xb6, 0xaf, 0x2c, 0x5e, 0x23, 0x6a, 0xab,
0xe3, 0x23, 0xf0, 0xeb, 0xa5, 0xc6, 0xd2, 0x4f, 0x7c, 0x6d, 0x7f, 0x6d, 0x42, 0x33, 0x16, 0x97,
0x2c, 0x2b, 0x5d, 0x47, 0xaa, 0xe4, 0x49, 0xeb, 0xd8, 0x0b, 0xdf, 0x40, 0x17, 0x77, 0x22, 0xc7,
0xd5, 0x43, 0x84, 0x93, 0x6e, 0x1f, 0xa2, 0x3f, 0xdd, 0x85, 0x86, 0xbc, 0xbd, 0xb9, 0x67, 0x37,
0x9f, 0x3e, 0xad, 0xec, 0x38, 0x47, 0xb9, 0x24, 0x72, 0x0f, 0x0a, 0xd9, 0x3a, 0x35, 0x62, 0xe3,
0x9d, 0x1a, 0x73, 0x37, 0xeb, 0x79, 0xff, 0x6d, 0xb7, 0xfa, 0x69, 0x0f, 0x3f, 0x8f, 0x7f, 0x05,
0x00, 0x00, 0xff, 0xff, 0x56, 0x20, 0xfa, 0x8b, 0x73, 0x05, 0x00, 0x00,
}

View File

@@ -3,30 +3,66 @@ option go_package = "proto";
package plugins;
import "google/protobuf/timestamp.proto";
// Message represents a simple message sent to the Echo service.
message TsdbRequest {
int64 from = 1;
int64 to = 2;
repeated TsdbQuery queries = 3;
}
message TsdbQuery {
string queryJson = 1;
Timerange timerange = 1;
DatasourceInfo datasource = 2;
repeated Query queries = 3;
}
message TsdbResponse {
string error = 1;
string errorString = 2;
string refId = 3;
string metaJson = 4;
repeated TsdbSeries series = 5;
//repeat TsdbTables tables = x;
message Query {
string refId = 1;
string modelJson = 2;
int64 MaxDataPoints = 3;
int64 intervalMs = 4;
DatasourceInfo datasource = 5;
}
message Timerange {
string from = 1;
string to = 2;
google.protobuf.Timestamp now = 3;
}
message Response {
string message = 1;
repeated QueryResult results = 2;
}
message QueryResult {
string error = 1;
string errorString = 2;
string refId = 3;
string metaJson = 4;
repeated TsdbSeries series = 5;
//repeat TsdbTables tables = x;
}
message DatasourceInfo {
string name = 1;
string type = 2;
string access = 3;
string url = 4;
bool basicAuth = 5;
string basicAuthUser = 6;
string basicAuthPassword = 7;
string jsonData = 8;
string secureJsonData = 9;
}
message TsdbSeries {
string name = 1;
map<string, string> tags = 2;
repeated Point points = 3;
}
message Point {
google.protobuf.Timestamp timestamp = 1;
double value = 2;
}
service TsdbPlugin {
rpc Get(TsdbRequest) returns (TsdbResponse);
rpc Query(TsdbQuery) returns (Response);
}