mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
93 lines
2.4 KiB
Go
93 lines
2.4 KiB
Go
|
package pipeline
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"reflect"
|
||
|
"time"
|
||
|
|
||
|
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||
|
)
|
||
|
|
||
|
type ChangeLogOutputConfig struct {
|
||
|
FieldName string `json:"fieldName"`
|
||
|
Channel string `json:"channel"`
|
||
|
}
|
||
|
|
||
|
// ChangeLogOutput can monitor value changes of the specified field and output
|
||
|
// special change frame to the configured channel.
|
||
|
type ChangeLogOutput struct {
|
||
|
frameStorage FrameGetSetter
|
||
|
config ChangeLogOutputConfig
|
||
|
}
|
||
|
|
||
|
func NewChangeLogOutput(frameStorage FrameGetSetter, config ChangeLogOutputConfig) *ChangeLogOutput {
|
||
|
return &ChangeLogOutput{frameStorage: frameStorage, config: config}
|
||
|
}
|
||
|
|
||
|
func (l ChangeLogOutput) Output(_ context.Context, vars OutputVars, frame *data.Frame) ([]*ChannelFrame, error) {
|
||
|
previousFrame, previousFrameOK, err := l.frameStorage.Get(vars.OrgID, l.config.Channel)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
fieldName := l.config.FieldName
|
||
|
|
||
|
previousFrameFieldIndex := -1
|
||
|
if previousFrameOK {
|
||
|
for i, f := range previousFrame.Fields {
|
||
|
if f.Name == fieldName {
|
||
|
previousFrameFieldIndex = i
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
currentFrameFieldIndex := -1
|
||
|
for i, f := range frame.Fields {
|
||
|
if f.Name == fieldName {
|
||
|
currentFrameFieldIndex = i
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var previousValue interface{}
|
||
|
if previousFrameFieldIndex >= 0 {
|
||
|
// Take last value for the field.
|
||
|
previousValue = previousFrame.Fields[previousFrameFieldIndex].At(previousFrame.Fields[previousFrameFieldIndex].Len() - 1)
|
||
|
}
|
||
|
|
||
|
fTime := data.NewFieldFromFieldType(data.FieldTypeTime, 0)
|
||
|
fTime.Name = "time"
|
||
|
f1 := data.NewFieldFromFieldType(frame.Fields[currentFrameFieldIndex].Type(), 0)
|
||
|
f1.Name = "old"
|
||
|
f2 := data.NewFieldFromFieldType(frame.Fields[currentFrameFieldIndex].Type(), 0)
|
||
|
f2.Name = "new"
|
||
|
|
||
|
if currentFrameFieldIndex >= 0 {
|
||
|
for i := 0; i < frame.Fields[currentFrameFieldIndex].Len(); i++ {
|
||
|
currentValue := frame.Fields[currentFrameFieldIndex].At(i)
|
||
|
if !reflect.DeepEqual(
|
||
|
previousValue,
|
||
|
currentValue,
|
||
|
) {
|
||
|
fTime.Append(time.Now())
|
||
|
f1.Append(previousValue)
|
||
|
f2.Append(currentValue)
|
||
|
previousValue = currentValue
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if fTime.Len() > 0 {
|
||
|
changeFrame := data.NewFrame("change", fTime, f1, f2)
|
||
|
err := l.frameStorage.Set(vars.OrgID, l.config.Channel, frame)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return []*ChannelFrame{{
|
||
|
Channel: l.config.Channel,
|
||
|
Frame: changeFrame,
|
||
|
}}, nil
|
||
|
}
|
||
|
|
||
|
return nil, l.frameStorage.Set(vars.OrgID, l.config.Channel, frame)
|
||
|
}
|