mirror of
https://github.com/grafana/grafana.git
synced 2025-08-01 05:31:49 +08:00
Live: test pipeline convert endpoint (#39480)
This commit is contained in:
@ -438,6 +438,7 @@ func (hs *HTTPServer) registerRoutes() {
|
|||||||
// POST Live data to be processed according to channel rules.
|
// POST Live data to be processed according to channel rules.
|
||||||
liveRoute.Post("/push/:streamId/:path", hs.LivePushGateway.HandlePath)
|
liveRoute.Post("/push/:streamId/:path", hs.LivePushGateway.HandlePath)
|
||||||
liveRoute.Get("/channel-rules", routing.Wrap(hs.Live.HandleChannelRulesListHTTP), reqOrgAdmin)
|
liveRoute.Get("/channel-rules", routing.Wrap(hs.Live.HandleChannelRulesListHTTP), reqOrgAdmin)
|
||||||
|
liveRoute.Post("/pipeline-convert-test", routing.Wrap(hs.Live.HandlePipelineConvertTestHTTP), reqOrgAdmin)
|
||||||
liveRoute.Post("/channel-rules", routing.Wrap(hs.Live.HandleChannelRulesPostHTTP), reqOrgAdmin)
|
liveRoute.Post("/channel-rules", routing.Wrap(hs.Live.HandleChannelRulesPostHTTP), reqOrgAdmin)
|
||||||
liveRoute.Put("/channel-rules", routing.Wrap(hs.Live.HandleChannelRulesPutHTTP), reqOrgAdmin)
|
liveRoute.Put("/channel-rules", routing.Wrap(hs.Live.HandleChannelRulesPutHTTP), reqOrgAdmin)
|
||||||
liveRoute.Delete("/channel-rules", routing.Wrap(hs.Live.HandleChannelRulesDeleteHTTP), reqOrgAdmin)
|
liveRoute.Delete("/channel-rules", routing.Wrap(hs.Live.HandleChannelRulesDeleteHTTP), reqOrgAdmin)
|
||||||
|
@ -885,6 +885,85 @@ func (g *GrafanaLive) HandleChannelRulesListHTTP(c *models.ReqContext) response.
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ConvertDryRunRequest struct {
|
||||||
|
ChannelRules []pipeline.ChannelRule `json:"channelRules"`
|
||||||
|
Channel string `json:"channel"`
|
||||||
|
Data string `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConvertDryRunResponse struct {
|
||||||
|
ChannelFrames []*pipeline.ChannelFrame `json:"channelFrames"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DryRunRuleStorage struct {
|
||||||
|
ChannelRules []pipeline.ChannelRule
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *DryRunRuleStorage) CreateChannelRule(_ context.Context, _ int64, _ pipeline.ChannelRule) (pipeline.ChannelRule, error) {
|
||||||
|
return pipeline.ChannelRule{}, errors.New("not implemented by dry run rule storage")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *DryRunRuleStorage) UpdateChannelRule(_ context.Context, _ int64, _ pipeline.ChannelRule) (pipeline.ChannelRule, error) {
|
||||||
|
return pipeline.ChannelRule{}, errors.New("not implemented by dry run rule storage")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *DryRunRuleStorage) DeleteChannelRule(_ context.Context, _ int64, _ string) error {
|
||||||
|
return errors.New("not implemented by dry run rule storage")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *DryRunRuleStorage) ListRemoteWriteBackends(_ context.Context, _ int64) ([]pipeline.RemoteWriteBackend, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *DryRunRuleStorage) ListChannelRules(_ context.Context, _ int64) ([]pipeline.ChannelRule, error) {
|
||||||
|
return s.ChannelRules, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandlePipelineConvertTestHTTP ...
|
||||||
|
func (g *GrafanaLive) HandlePipelineConvertTestHTTP(c *models.ReqContext) response.Response {
|
||||||
|
body, err := ioutil.ReadAll(c.Req.Body)
|
||||||
|
if err != nil {
|
||||||
|
return response.Error(http.StatusInternalServerError, "Error reading body", err)
|
||||||
|
}
|
||||||
|
var req ConvertDryRunRequest
|
||||||
|
err = json.Unmarshal(body, &req)
|
||||||
|
if err != nil {
|
||||||
|
return response.Error(http.StatusBadRequest, "Error decoding request", err)
|
||||||
|
}
|
||||||
|
storage := &DryRunRuleStorage{
|
||||||
|
ChannelRules: req.ChannelRules,
|
||||||
|
}
|
||||||
|
builder := &pipeline.StorageRuleBuilder{
|
||||||
|
Node: g.node,
|
||||||
|
ManagedStream: g.ManagedStreamRunner,
|
||||||
|
FrameStorage: pipeline.NewFrameStorage(),
|
||||||
|
RuleStorage: storage,
|
||||||
|
ChannelHandlerGetter: g,
|
||||||
|
}
|
||||||
|
channelRuleGetter := pipeline.NewCacheSegmentedTree(builder)
|
||||||
|
pipe, err := pipeline.New(channelRuleGetter)
|
||||||
|
if err != nil {
|
||||||
|
return response.Error(http.StatusInternalServerError, "Error creating pipeline", err)
|
||||||
|
}
|
||||||
|
rule, ok, err := channelRuleGetter.Get(c.OrgId, req.Channel)
|
||||||
|
if err != nil {
|
||||||
|
return response.Error(http.StatusInternalServerError, "Error getting channel rule", err)
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
return response.Error(http.StatusNotFound, "No rule found", nil)
|
||||||
|
}
|
||||||
|
channelFrames, ok, err := pipe.DataToChannelFrames(c.Req.Context(), *rule, c.OrgId, req.Channel, []byte(req.Data))
|
||||||
|
if err != nil {
|
||||||
|
return response.Error(http.StatusInternalServerError, "Error converting data", err)
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
return response.Error(http.StatusNotFound, "No converter found", nil)
|
||||||
|
}
|
||||||
|
return response.JSON(http.StatusOK, ConvertDryRunResponse{
|
||||||
|
ChannelFrames: channelFrames,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// HandleChannelRulesPostHTTP ...
|
// HandleChannelRulesPostHTTP ...
|
||||||
func (g *GrafanaLive) HandleChannelRulesPostHTTP(c *models.ReqContext) response.Response {
|
func (g *GrafanaLive) HandleChannelRulesPostHTTP(c *models.ReqContext) response.Response {
|
||||||
body, err := ioutil.ReadAll(c.Req.Body)
|
body, err := ioutil.ReadAll(c.Req.Body)
|
||||||
|
@ -20,8 +20,8 @@ import (
|
|||||||
// then frame processing will be redirected to a corresponding channel rule.
|
// then frame processing will be redirected to a corresponding channel rule.
|
||||||
// TODO: avoid recursion, increment a counter while frame travels over pipeline steps, make it configurable.
|
// TODO: avoid recursion, increment a counter while frame travels over pipeline steps, make it configurable.
|
||||||
type ChannelFrame struct {
|
type ChannelFrame struct {
|
||||||
Channel string
|
Channel string `json:"channel"`
|
||||||
Frame *data.Frame
|
Frame *data.Frame `json:"frame"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vars has some helpful things pipeline entities could use.
|
// Vars has some helpful things pipeline entities could use.
|
||||||
@ -111,7 +111,6 @@ type Pipeline struct {
|
|||||||
|
|
||||||
// New creates new Pipeline.
|
// New creates new Pipeline.
|
||||||
func New(ruleGetter ChannelRuleGetter) (*Pipeline, error) {
|
func New(ruleGetter ChannelRuleGetter) (*Pipeline, error) {
|
||||||
logger.Info("Live pipeline initialization")
|
|
||||||
p := &Pipeline{
|
p := &Pipeline{
|
||||||
ruleGetter: ruleGetter,
|
ruleGetter: ruleGetter,
|
||||||
}
|
}
|
||||||
@ -133,7 +132,7 @@ func (p *Pipeline) ProcessInput(ctx context.Context, orgID int64, channelID stri
|
|||||||
if !ok {
|
if !ok {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
channelFrames, ok, err := p.dataToChannelFrames(ctx, *rule, orgID, channelID, body)
|
channelFrames, ok, err := p.DataToChannelFrames(ctx, *rule, orgID, channelID, body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
@ -147,7 +146,7 @@ func (p *Pipeline) ProcessInput(ctx context.Context, orgID int64, channelID stri
|
|||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Pipeline) dataToChannelFrames(ctx context.Context, rule LiveChannelRule, orgID int64, channelID string, body []byte) ([]*ChannelFrame, bool, error) {
|
func (p *Pipeline) DataToChannelFrames(ctx context.Context, rule LiveChannelRule, orgID int64, channelID string, body []byte) ([]*ChannelFrame, bool, error) {
|
||||||
if rule.Converter == nil {
|
if rule.Converter == nil {
|
||||||
return nil, false, nil
|
return nil, false, nil
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user